[cdo] 07/11: Upstream release 1.8.1

Alastair McKinstry mckinstry at moszumanska.debian.org
Thu Apr 20 10:40:38 UTC 2017


This is an automated email from the git hooks/post-receive script.

mckinstry pushed a commit to branch debian/master
in repository cdo.

commit da1935f77385fcffd637036e4edac455fe637ff6
Author: Alastair McKinstry <mckinstry at debian.org>
Date:   Thu Apr 20 09:09:39 2017 +0100

    Upstream release 1.8.1
---
 ChangeLog                                   |   88 +-
 Makefile.in                                 |    1 +
 NEWS                                        |   20 +
 OPERATORS                                   |   11 +-
 cdo.spec                                    |    2 +-
 config/default                              |    7 +-
 configure                                   |  163 ++-
 configure.ac                                |    7 +-
 contrib/Makefile.in                         |    1 +
 contrib/cdoCompletion.bash                  |   17 +-
 contrib/cdoCompletion.tcsh                  |   17 +-
 contrib/cdoCompletion.zsh                   |   17 +-
 doc/cdo.pdf                                 |  Bin 2676082 -> 2686871 bytes
 doc/cdo_refcard.pdf                         |  Bin 94001 -> 95775 bytes
 libcdi/ChangeLog                            |   55 +
 libcdi/Makefile.in                          |    1 +
 libcdi/NEWS                                 |    2 +-
 libcdi/aclocal.m4                           |    1 +
 libcdi/app/Makefile.in                      |    1 +
 libcdi/app/printinfo.h                      |   35 +-
 libcdi/cdi.settings.in                      |    3 -
 libcdi/configure                            |  108 +-
 libcdi/configure.ac                         |    4 +-
 libcdi/examples/Makefile.in                 |    1 +
 libcdi/examples/pio/Makefile.in             |    1 +
 libcdi/examples/pio/compareResourcesArray.c |   11 +-
 libcdi/interfaces/Makefile.in               |    1 +
 libcdi/m4/acx_options.m4                    |   13 +
 libcdi/m4/acx_prog_cc_posix.m4              |   71 ++
 libcdi/src/Makefile.in                      |    1 +
 libcdi/src/binary.h                         |    6 +-
 libcdi/src/calendar.c                       |   12 +-
 libcdi/src/cdf_int.c                        |    9 +
 libcdi/src/cdf_int.h                        |    2 +
 libcdi/src/cdf_lazy_grid.c                  |    2 +-
 libcdi/src/cdf_util.c                       |   21 +-
 libcdi/src/cdf_write.c                      |   46 +-
 libcdi/src/cdi.h                            |   10 +-
 libcdi/src/cdi.inc                          |  470 +++++----
 libcdi/src/cdiFortran.c                     |   23 +-
 libcdi/src/cdi_int.c                        |   43 +
 libcdi/src/cdi_int.h                        |   13 +-
 libcdi/src/cdipio.inc                       |   32 +-
 libcdi/src/cdipioFortran.c                  |   17 +-
 libcdi/src/cfortran.h                       |   15 +-
 libcdi/src/cgribexlib.c                     |    2 +-
 libcdi/src/config.h.in                      |    3 +
 libcdi/src/error.h                          |    6 +-
 libcdi/src/file.c                           |  237 ++---
 libcdi/src/grb_read.c                       |    1 -
 libcdi/src/grb_write.c                      |   89 +-
 libcdi/src/gribapi.h                        |    2 +-
 libcdi/src/gribapi_utilities.c              |  169 ++-
 libcdi/src/gribapi_utilities.h              |    5 +
 libcdi/src/grid.c                           |  635 +++++++-----
 libcdi/src/grid.h                           |   39 +-
 libcdi/src/iterator_fallback.c              |    4 +
 libcdi/src/iterator_fallback.h              |    6 +
 libcdi/src/iterator_grib.c                  |   55 +-
 libcdi/src/iterator_grib.h                  |    4 +
 libcdi/src/mo_cdi.f90                       |   88 +-
 libcdi/src/pio_interface.c                  |    6 +-
 libcdi/src/pio_mpi_fw_at_all.c              |    2 +-
 libcdi/src/pio_mpi_fw_at_reblock.c          |    2 +-
 libcdi/src/pio_roles.c                      |    2 +-
 libcdi/src/pio_util.c                       |    2 +-
 libcdi/src/pio_util.h                       |    2 +-
 libcdi/src/pkgconfig/cdi.pc.in              |    4 +-
 libcdi/src/pkgconfig/cdipio.pc.in           |    4 +-
 libcdi/src/serialize.h                      |    2 +-
 libcdi/src/stream.c                         |   33 +-
 libcdi/src/stream_cdf_i.c                   |  125 ++-
 libcdi/src/stream_cdf_o.c                   |  137 +--
 libcdi/src/stream_cgribex.c                 |  315 ++++--
 libcdi/src/stream_cgribex.h                 |    5 +
 libcdi/src/stream_ext.c                     |    4 +-
 libcdi/src/stream_grb.c                     |   74 +-
 libcdi/src/stream_grb.h                     |   32 +
 libcdi/src/stream_gribapi.c                 |  617 +++++++++--
 libcdi/src/stream_gribapi.h                 |   11 +
 libcdi/src/stream_history.c                 |   24 +-
 libcdi/src/stream_ieg.c                     |   12 +-
 libcdi/src/stream_srv.c                     |    2 +-
 libcdi/src/stream_write.c                   |   10 +-
 libcdi/src/table.c                          |   95 +-
 libcdi/src/taxis.c                          |   85 +-
 libcdi/src/taxis.h                          |    4 +-
 libcdi/src/util.c                           |   67 +-
 libcdi/src/varscan.c                        |   30 +-
 libcdi/src/vlist.h                          |    2 +-
 libcdi/tests/Makefile.in                    |    1 +
 libcdi/tests/pio_write.c                    |    4 +
 libcdi/tests/simple_model.c                 |   17 +-
 libcdi/tests/stream_cksum.c                 |  191 ++--
 m4/acx_options.m4                           |   13 +
 src/Adisit.c                                |    4 +-
 src/Afterburner.c                           |   34 +-
 src/Arith.c                                 |   28 +-
 src/Arithlat.c                              |    3 +-
 src/Change_e5slm.c                          |   21 +-
 src/Collgrid.c                              |   76 +-
 src/Copy.c                                  |   16 +
 src/Derivepar.c                             |    9 +-
 src/Distgrid.c                              |    4 +-
 src/Ensstat.c                               |   15 +-
 src/Exprf.c                                 |   10 +-
 src/Filedes.c                               |    2 +-
 src/Fillmiss.c                              |    6 +-
 src/Gradsdes.c                              |   37 +-
 src/Gridcell.c                              |    4 +-
 src/Info.c                                  |  334 +++---
 src/Invert.c                                |  178 ++--
 src/Invertlev.c                             |    2 -
 src/Makefile.am                             |   10 +-
 src/Makefile.in                             |  232 +++--
 src/Math.c                                  |    4 +-
 src/Pressure.c                              |   63 +-
 src/Remap.c                                 |  148 +--
 src/Rotuv.c                                 |   42 +-
 src/Runstat.c                               |    1 -
 src/Samplegrid.c                            |  240 +++++
 src/Selbox.c                                |   30 +-
 src/Select.c                                |   51 +-
 src/{Selindex.c => Selgridcell.c}           |   32 +-
 src/Selmulti.c                              | 1180 +++++++++++++++++++++
 src/Selrec.c                                |    3 -
 src/Seltime.c                               |    9 +-
 src/Selvar.c                                |    3 -
 src/Setgrid.c                               |   33 +-
 src/Settime.c                               |    4 +-
 src/Showinfo.c                              |   70 +-
 src/Sinfo.c                                 |   38 +-
 src/Verifygrid.c                            |   10 +
 src/Vertintml.c                             |   17 +-
 src/WindTrans.c                             | 1483 +++++++++++++++++++++++++++
 src/after_fctrans.c                         |   20 +-
 src/after_sptrans.c                         |   17 +-
 src/array.c                                 |   23 +
 src/array.h                                 |    1 +
 src/cdo.c                                   |   55 +
 src/cdo_read.c                              |   60 ++
 src/cdo_vlist.c                             |   13 +-
 src/config.h.in                             |    3 +
 src/expr.c                                  |    4 +-
 src/fieldc.c                                |   14 +-
 src/grid.c                                  |  780 ++++----------
 src/grid.h                                  |   74 +-
 src/grid_area.c                             |    3 -
 src/grid_define.c                           |  404 ++++++++
 src/grid_lcc.c                              |  332 ------
 src/grid_print.c                            |   37 +-
 src/grid_proj.c                             |  477 +++++++++
 src/grid_proj.h                             |   24 +
 src/grid_read.c                             |   32 +-
 src/grid_rot.c                              |   38 +-
 src/griddes.c                               |  167 +--
 src/griddes.h                               |   28 +-
 src/griddes_h5.c                            |    2 -
 src/griddes_nc.c                            |   12 +-
 src/gridreference.c                         |   40 +-
 src/institution.c                           |   24 +-
 src/listarray.c                             |    4 +-
 src/listarray.h                             |    4 +-
 src/modules.c                               |   31 +-
 src/namelist.c                              |    8 +-
 src/namelist_parser.c                       |   10 +-
 src/operator_help.h                         |  137 ++-
 src/printinfo.h                             |   27 +-
 src/remap_bilinear_scrip.c                  |   31 +-
 src/remap_distwgt.c                         |   24 +-
 src/remap_search_latbins.c                  |   75 +-
 src/remaplib.c                              |   41 +-
 src/sellist.c                               |   22 +-
 src/specspace.c                             |   10 +-
 src/stdnametable.c                          |   41 +
 src/stdnametable.h                          |    6 +
 src/table.c                                 |    5 +-
 src/util.c                                  |   29 +-
 src/util.h                                  |    4 +
 src/zaxis.c                                 |   13 +-
 test/Afterburner.test.in                    |    2 +-
 test/Arith.test.in                          |    2 +-
 test/Arithc.test.in                         |    2 +-
 test/Cat.test.in                            |    2 +-
 test/Collgrid.test.in                       |    2 +-
 test/Comp.test.in                           |    2 +-
 test/Compc.test.in                          |    2 +-
 test/Copy_netcdf.test.in                    |    2 +-
 test/Detrend.test.in                        |    2 +-
 test/EOF.test.in                            |    2 +-
 test/Enspctl.test.in                        |    2 +-
 test/Ensstat.test.in                        |    2 +-
 test/Expr.test.in                           |    2 +-
 test/File.test.in                           |    2 +-
 test/Fldpctl.test.in                        |    2 +-
 test/Fldstat.test.in                        |    2 +-
 test/Genweights.test.in                     |    2 +-
 test/Gradsdes.test.in                       |    2 +-
 test/Gridarea.test.in                       |    2 +-
 test/Gridboxstat.test.in                    |    2 +-
 test/Makefile.am                            |    2 +-
 test/Makefile.in                            |   52 +-
 test/MapReduce.test.in                      |    4 +-
 test/Merstat.test.in                        |    2 +-
 test/Multiyearstat.test.in                  |    2 +-
 test/Ninfo.test.in                          |    3 +-
 test/Read_grib.test.in                      |    2 +-
 test/Read_netcdf.test.in                    |    2 +-
 test/Remap.test.in                          |    2 +-
 test/Remap2.test.in                         |   59 ++
 test/Runstat.test.in                        |    2 +-
 test/Seasstat.test.in                       |    2 +-
 test/Select.test.in                         |    2 +-
 test/Spectral.test.in                       |    2 +-
 test/Timselstat.test.in                     |    2 +-
 test/Timstat.test.in                        |    2 +-
 test/Vertint.test.in                        |    2 +-
 test/Vertstat.test.in                       |    2 +-
 test/Zonstat.test.in                        |    2 +-
 test/data/Makefile.am                       |   12 +-
 test/data/Makefile.in                       |   15 +-
 test/data/spain.grid                        |    7 +
 test/data/tsurf_spain.grb                   |  Bin 0 -> 896 bytes
 test/data/tsurf_spain_bic_def_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_bic_off_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_bic_on_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_bil_def_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_bil_off_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_bil_on_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_con_def_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_con_off_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_con_on_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_dis_def_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_dis_off_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_dis_on_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_laf_def_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_laf_off_ref           |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_laf_on_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_nn_def_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_nn_off_ref            |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_nn_on_ref             |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_ycon_def_ref          |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_ycon_off_ref          |  Bin 0 -> 1488 bytes
 test/data/tsurf_spain_ycon_on_ref           |  Bin 0 -> 1488 bytes
 test/threads.test.in                        |    2 +-
 test/tsformat.test.in                       |    2 +-
 test/wildcard.test.in                       |    2 +-
 247 files changed, 8885 insertions(+), 3697 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7f2cb81..938ae8c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,89 @@
+2017-04-13  Uwe Schulzweida
+
+	* Using CDI library version 1.8.1
+	* Version 1.8.1 release
+
+2017-04-10  Uwe Schulzweida
+
+	* Use Proj4 to convert GRIB LCC grids to geographic coordinates
+
+2017-04-09  Uwe Schulzweida
+
+	* Refactor GRID_LCC to GRID_PROJECTION
+
+2017-04-07  Uwe Schulzweida
+
+	* setpartab: added support for values in single quotes [Bug #7662]
+
+2017-04-03  Uwe Schulzweida
+
+	* Arith: set varID2 to varID (bug fix for variables with different grid size)
+
+2017-03-29  Uwe Schulzweida
+
+	* collgrid: combination of nx and names does not work (bug fix)
+
+2017-03-24  Uwe Schulzweida
+
+	* remap_grids_init: bug fix for CDI_PROJ_LCC
+
+2017-03-21  Uwe Schulzweida
+
+	* remapdis: potentialy wrong results on non global grids [Bug #7626]  (bug was introduced in last revision)
+
+2017-03-13  Uwe Schulzweida
+
+	* selindexbox: added support for LCC grid
+
+2017-03-09  Uwe Schulzweida
+
+	* New operator delgridcell - Delete grid cells by indexes
+
+2017-03-06  Uwe Schulzweida
+
+	* New operator selmulti:  Select multiple fields (patch from Michal Koutek, KMNI)
+	* New operator delmulti:  Delete multiple fields (patch from Michal Koutek, KMNI)
+	* New operator changemulti:  Change identication of multiple fields (patch from Michal Koutek, KMNI)
+
+2017-03-03  Uwe Schulzweida
+
+	* New operator rotuvNorth: Rotate grid-relative wind(u,v) to North_pole-relative (patch from Michal Koutek, KMNI)
+	* New operator projuvLatLon: Cylindrical Equidistant projection (patch from Michal Koutek, KMNI)
+
+2017-02-28  Uwe Schulzweida
+
+	* New operator uvDestag: Destaggering of wind components (patch from Michal Koutek, KMNI)
+
+2017-02-27  Uwe Schulzweida
+
+	* Added support for grid flag uvRelativeToGrid
+
+2017-02-24  Uwe Schulzweida
+
+	* New operator usegridnumber (patch from Michal Koutek, KMNI)
+
+2017-02-23  Uwe Schulzweida
+
+	* New operator showgrid: show grids (patch from Michal Koutek, KMNI)
+
+2017-02-22  Uwe Schulzweida
+
+	* option -k auto: set chunk_size_max to 65536.
+
+2017-02-21  Uwe Schulzweida
+
+	* New operator xinfon:
+
+2017-02-20  Uwe Schulzweida
+
+	* New operator samplegrid: resample grid (patch from Michal Koutek, KMNI)
+	* New operator subgrid: selindexbox for LCC grids (patch from Michal Koutek, KMNI)
+	* setgridtype,curvilinear: bug fix for source gridtype GRID_LCC
+
+2017-02-16  Uwe Schulzweida
+
+	* invertlat: added support for gridtype projection
+
 2017-02-14  Uwe Schulzweida
 
 	* Using CDI library version 1.8.0
@@ -121,7 +207,7 @@
 
 2016-07-29  Uwe Schulzweida
 
-	* New operator selindex - Select grid indices
+	* New operator selindex - Select grid cells by indices
 
 2016-07-18  Uwe Schulzweida
 
diff --git a/Makefile.in b/Makefile.in
index bab544c..e25bcae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -213,6 +213,7 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BASH = @BASH@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
diff --git a/NEWS b/NEWS
index 1d31332..1a4f622 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,26 @@
 CDO NEWS
 --------
 
+Version 1.8.1 (6 April 2017):
+
+   New features:
+     * selindexbox: added support for LCC grid
+   New operators:
+     * selgridcell - Select grid cells
+     * delgridcell - Delete grid cells
+   New operators (KMNI contribution):
+     * selmulti - Select multiple fields
+     * delmulti - Delete multiple fields
+     * changemulti - Change identication of multiple fields
+     * samplegrid - Resample grid
+     * uvDestag - Destaggering of wind components
+     * rotuvNorth - Rotate u/v wind to North pole
+     * projuvLatLon - Cylindrical Equidistant projection
+   Fixed bugs:
+     * collgrid: combination of nx and names does not work
+     * Remapping bug for non global grids [Bug #7625]
+     * remapdis and remapcon produces wrong results for some grid combinations [Bug #7626] (introduced in last revision)
+
 Version 1.8.0 (26 October 2016):
 
    New features:
diff --git a/OPERATORS b/OPERATORS
index a8b555d..f5ca3d2 100644
--- a/OPERATORS
+++ b/OPERATORS
@@ -69,6 +69,9 @@ Operator catalog:
 -------------------------------------------------------------
    Select        select          Select fields
    Select        delete          Delete fields
+   Selmulti      selmulti        Select multiple fields
+   Selmulti      delmulti        Delete multiple fields
+   Selmulti      changemulti     Change identication of multiple fields
    Selvar        selparam        Select parameters by identifier
    Selvar        delparam        Delete parameters by identifier
    Selvar        selcode         Select parameters by code number
@@ -94,6 +97,9 @@ Operator catalog:
    Seltime       selsmon         Select single month
    Selbox        sellonlatbox    Select a longitude/latitude box
    Selbox        selindexbox     Select an index box
+   Selgridcell   selgridcell     Select grid cells
+   Selgridcell   delgridcell     Delete grid cells
+   Samplegrid    samplegrid      Resample grid
 -------------------------------------------------------------
    Conditional selection
 -------------------------------------------------------------
@@ -121,7 +127,7 @@ Operator catalog:
 -------------------------------------------------------------
    Modification
 -------------------------------------------------------------
-   Setattributes setattribute    Set attributes
+   Setattribute  setattribute    Set attributes
    Setpartab     setpartabp      Set parameter table
    Setpartab     setpartabn      Set parameter table
    Set           setcodetab      Set parameter code table
@@ -532,6 +538,9 @@ Operator catalog:
    Vargen        topo            Create a field with topography
    Vargen        for             Create a time series
    Vargen        stdatm          Create values for pressure and temperature for hydrostatic atmosphere
+   WindTrans     uvDestag        Destaggering of u/v wind components
+   WindTrans     rotuvNorth      Rotate u/v wind to North pole.
+   WindTrans     projuvLatLon    Cylindrical Equidistant projection
    Rotuv         rotuvb          Backward rotation
    Mastrfu       mastrfu         Mass stream function
    Derivepar     sealevelpressure Sea level pressure
diff --git a/cdo.spec b/cdo.spec
index 2b81c8c..1ff8fc3 100644
--- a/cdo.spec
+++ b/cdo.spec
@@ -4,7 +4,7 @@
 
 Name:           cdo
 #BuildRequires:  
-Version:        1.8.0
+Version:        1.8.1
 Release:        1
 Summary:        Climate Data Operators
 License:        GNU GENERAL PUBLIC LICENSE Version 2, June 1991
diff --git a/config/default b/config/default
index 7d80d25..c019d92 100755
--- a/config/default
+++ b/config/default
@@ -85,9 +85,10 @@ case "${HOSTNAME}" in
 #                 --with-curl=/opt/local"
         CDOLIBS="--enable-nearpt3 \
                  --with-fftw3 \
-                 --with-grib_api=$HOME/local/gribapi-1.13.0 \
-                 --with-netcdf=$HOME/local \
-                 --with-hdf5=$HOME/local \
+                 --with-szlib=$HOME/local \
+                 --with-grib_api=$HOME/local/grib_api-1.21.0 \
+                 --with-netcdf=$HOME/local/netcdf-c-4.4.1.1 \
+                 --with-hdf5=$HOME/local/hdf5-1.8.18 \
                  --with-libxml2=/opt/local \
                  --with-proj=/opt/local"
 
diff --git a/configure b/configure
index 9423cfa..6eb64fc 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for cdo 1.8.0.
+# Generated by GNU Autoconf 2.68 for cdo 1.8.1.
 #
 # Report bugs to <http://mpimet.mpg.de/cdo>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdo'
 PACKAGE_TARNAME='cdo'
-PACKAGE_VERSION='1.8.0'
-PACKAGE_STRING='cdo 1.8.0'
+PACKAGE_VERSION='1.8.1'
+PACKAGE_STRING='cdo 1.8.1'
 PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdo'
 PACKAGE_URL=''
 
@@ -628,6 +628,8 @@ BUILD_AVX_TESTS_FALSE
 BUILD_AVX_TESTS_TRUE
 BUILD_SSE42_TESTS_FALSE
 BUILD_SSE42_TESTS_TRUE
+ENABLE_HIRLAM_EXTENSIONS_FALSE
+ENABLE_HIRLAM_EXTENSIONS_TRUE
 ENABLE_ALL_STATIC_FALSE
 ENABLE_ALL_STATIC_TRUE
 subdirs
@@ -688,6 +690,7 @@ CXXFLAGS
 AS
 OPENMP_CFLAGS
 CXX
+BASH
 CPP
 OTOOL64
 OTOOL
@@ -838,6 +841,7 @@ with_magics
 with_libxml2
 enable_cdi_lib
 enable_all_static
+enable_hirlam_extensions
 enable_cxx
 '
       ac_precious_vars='build_alias
@@ -1395,7 +1399,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures cdo 1.8.0 to adapt to many kinds of systems.
+\`configure' configures cdo 1.8.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1465,7 +1469,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdo 1.8.0:";;
+     short | recursive ) echo "Configuration of cdo 1.8.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1499,6 +1503,8 @@ Optional Features:
                           [default=no]
   --enable-all-static     build a completely statically linked CDO binary
                           [default=no]
+  --enable-hirlam-extensions
+                          HIRLAM extensions [default=no]
   --enable-cxx            Use CXX as default compiler [default=no]
 
 Optional Packages:
@@ -1613,7 +1619,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdo configure 1.8.0
+cdo configure 1.8.1
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2206,7 +2212,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by cdo $as_me 1.8.0, which was
+It was created by cdo $as_me 1.8.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3155,7 +3161,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdo'
- VERSION='1.8.0'
+ VERSION='1.8.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12000,6 +12006,106 @@ CC="$lt_save_CC"
 
 
 
+# bash
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}bash", so it can be a program name with args.
+set dummy ${ac_tool_prefix}bash; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_BASH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $BASH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_BASH="$BASH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_BASH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+BASH=$ac_cv_path_BASH
+if test -n "$BASH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BASH" >&5
+$as_echo "$BASH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_BASH"; then
+  ac_pt_BASH=$BASH
+  # Extract the first word of "bash", so it can be a program name with args.
+set dummy bash; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_BASH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_BASH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_BASH="$ac_pt_BASH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_ac_pt_BASH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_BASH=$ac_cv_path_ac_pt_BASH
+if test -n "$ac_pt_BASH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_BASH" >&5
+$as_echo "$ac_pt_BASH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_BASH" = x; then
+    BASH=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    BASH=$ac_pt_BASH
+  fi
+else
+  BASH="$ac_cv_path_BASH"
+fi
+
+
 # Check building environment
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
@@ -20833,6 +20939,35 @@ else
   ENABLE_ALL_STATIC_FALSE=
 fi
 
+#  ----------------------------------------------------------------------
+#  Build CDO with HIRLAM extensions
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HIRLAM extensions" >&5
+$as_echo_n "checking for HIRLAM extensions... " >&6; }
+# Check whether --enable-hirlam-extensions was given.
+if test "${enable_hirlam_extensions+set}" = set; then :
+  enableval=$enable_hirlam_extensions; if test "x$enable_hirlam_extensions" != "xno"; then :
+
+$as_echo "#define HIRLAM_EXTENSIONS 1" >>confdefs.h
+
+                     enable_hirlam_extensions=yes
+else
+  enable_hirlam_extensions=no
+fi
+else
+  enable_hirlam_extensions=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_hirlam_extensions" >&5
+$as_echo "$enable_hirlam_extensions" >&6; }
+ if test x$enable_hirlam_extensions = 'xyes'; then
+  ENABLE_HIRLAM_EXTENSIONS_TRUE=
+  ENABLE_HIRLAM_EXTENSIONS_FALSE='#'
+else
+  ENABLE_HIRLAM_EXTENSIONS_TRUE='#'
+  ENABLE_HIRLAM_EXTENSIONS_FALSE=
+fi
+
+#
 
 
 #  ----------------------------------------------------------------------
@@ -21070,7 +21205,7 @@ ac_config_files="$ac_config_files test/File.test test/Read_grib.test test/Read_n
 
 ac_config_files="$ac_config_files test/Comp.test test/Compc.test"
 
-ac_config_files="$ac_config_files test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test"
+ac_config_files="$ac_config_files test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test test/Remap2.test"
 
 ac_config_files="$ac_config_files test/EOF.test test/Select.test test/Spectral.test test/Vertint.test"
 
@@ -21241,6 +21376,10 @@ if test -z "${ENABLE_ALL_STATIC_TRUE}" && test -z "${ENABLE_ALL_STATIC_FALSE}";
   as_fn_error $? "conditional \"ENABLE_ALL_STATIC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${ENABLE_HIRLAM_EXTENSIONS_TRUE}" && test -z "${ENABLE_HIRLAM_EXTENSIONS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_HIRLAM_EXTENSIONS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${BUILD_SSE42_TESTS_TRUE}" && test -z "${BUILD_SSE42_TESTS_FALSE}"; then
   as_fn_error $? "conditional \"BUILD_SSE42_TESTS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -21662,7 +21801,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by cdo $as_me 1.8.0, which was
+This file was extended by cdo $as_me 1.8.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21728,7 +21867,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-cdo config.status 1.8.0
+cdo config.status 1.8.1
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
@@ -22245,6 +22384,7 @@ do
     "test/Gridarea.test") CONFIG_FILES="$CONFIG_FILES test/Gridarea.test" ;;
     "test/Genweights.test") CONFIG_FILES="$CONFIG_FILES test/Genweights.test" ;;
     "test/Remap.test") CONFIG_FILES="$CONFIG_FILES test/Remap.test" ;;
+    "test/Remap2.test") CONFIG_FILES="$CONFIG_FILES test/Remap2.test" ;;
     "test/EOF.test") CONFIG_FILES="$CONFIG_FILES test/EOF.test" ;;
     "test/Select.test") CONFIG_FILES="$CONFIG_FILES test/Select.test" ;;
     "test/Spectral.test") CONFIG_FILES="$CONFIG_FILES test/Spectral.test" ;;
@@ -23776,6 +23916,7 @@ _LT_EOF
     "test/Gridarea.test":F) chmod a+x "$ac_file" ;;
     "test/Genweights.test":F) chmod a+x "$ac_file" ;;
     "test/Remap.test":F) chmod a+x "$ac_file" ;;
+    "test/Remap2.test":F) chmod a+x "$ac_file" ;;
     "test/EOF.test":F) chmod a+x "$ac_file" ;;
     "test/Select.test":F) chmod a+x "$ac_file" ;;
     "test/Spectral.test":F) chmod a+x "$ac_file" ;;
diff --git a/configure.ac b/configure.ac
index 6f50636..7a8f2cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdo], [1.8.0], [http://mpimet.mpg.de/cdo])
+AC_INIT([cdo], [1.8.1], [http://mpimet.mpg.de/cdo])
 
 AC_DEFINE_UNQUOTED(CDO, ["$PACKAGE_VERSION"], [CDO version])
 
@@ -25,6 +25,9 @@ AM_PROG_AR
 AC_MSG_NOTICE([setting up libtool])
 LT_INIT
 
+# bash
+AC_PATH_TOOL([BASH],[bash],[:])
+
 # Check building environment
 AC_CHECK_TOOL([CC],[gcc],[:])
 AC_CHECK_TOOL([CXX],[g++],[:])
@@ -249,7 +252,7 @@ AC_PROG_AWK
 
 AC_CONFIG_FILES([test/File.test test/Read_grib.test test/Read_netcdf.test test/Copy_netcdf.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/Comp.test test/Compc.test],[chmod a+x "$ac_file"])
-AC_CONFIG_FILES([test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test],[chmod a+x "$ac_file"])
+AC_CONFIG_FILES([test/Cat.test test/Gridarea.test test/Genweights.test test/Remap.test test/Remap2.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/EOF.test test/Select.test test/Spectral.test test/Vertint.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/Timstat.test test/Timselstat.test test/Seasstat.test test/Runstat.test test/Multiyearstat.test],[chmod a+x "$ac_file"])
 AC_CONFIG_FILES([test/Gridboxstat.test test/Vertstat.test test/Fldstat.test test/Fldpctl.test test/Ensstat.test test/Enspctl.test],[chmod a+x "$ac_file"])
diff --git a/contrib/Makefile.in b/contrib/Makefile.in
index 652f7d3..9a402d7 100644
--- a/contrib/Makefile.in
+++ b/contrib/Makefile.in
@@ -123,6 +123,7 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BASH = @BASH@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
diff --git a/contrib/cdoCompletion.bash b/contrib/cdoCompletion.bash
index f3e9c41..214f34a 100644
--- a/contrib/cdoCompletion.bash
+++ b/contrib/cdoCompletion.bash
@@ -56,6 +56,7 @@ boxavg -boxavg \
 cat -cat \
 cdiread -cdiread \
 cdiwrite -cdiwrite \
+changemulti -changemulti \
 chcode -chcode \
 chlevel -chlevel \
 chlevelc -chlevelc \
@@ -98,6 +99,9 @@ del29feb -del29feb \
 delcode -delcode \
 delday -delday \
 delete -delete \
+delgridcell -delgridcell \
+delindex -delindex \
+delmulti -delmulti \
 delname -delname \
 delparam -delparam \
 deltap -deltap \
@@ -229,8 +233,6 @@ genlevelbounds -genlevelbounds \
 gennn -gennn \
 genycon -genycon \
 geopotheight -geopotheight \
-ggstat -ggstat \
-ggstats -ggstats \
 gheight -gheight \
 globavg -globavg \
 gmtcells -gmtcells \
@@ -436,6 +438,7 @@ pinfov -pinfov \
 pow -pow \
 pressure_fl -pressure_fl \
 pressure_hl -pressure_hl \
+projuvLatLon -projuvLatLon \
 random -random \
 reci -reci \
 reducegrid -reducegrid \
@@ -458,6 +461,8 @@ remapycon -remapycon \
 replace -replace \
 retocomplex -retocomplex \
 rhopot -rhopot \
+rotuvN -rotuvN \
+rotuvNorth -rotuvNorth \
 rotuvb -rotuvb \
 runavg -runavg \
 runmax -runmax \
@@ -469,6 +474,7 @@ runstd1 -runstd1 \
 runsum -runsum \
 runvar -runvar \
 runvar1 -runvar1 \
+samplegrid -samplegrid \
 scatter -scatter \
 sealevelpressure -sealevelpressure \
 seasavg -seasavg \
@@ -492,6 +498,7 @@ seldate -seldate \
 selday -selday \
 select -select \
 selgrid -selgrid \
+selgridcell -selgridcell \
 selgridname -selgridname \
 selhour -selhour \
 selindex -selindex \
@@ -502,6 +509,7 @@ sellonlatbox -sellonlatbox \
 selltype -selltype \
 selmon -selmon \
 selmonth -selmonth \
+selmulti -selmulti \
 selname -selname \
 seloperator -seloperator \
 selparam -selparam \
@@ -572,6 +580,7 @@ shifty -shifty \
 showcode -showcode \
 showdate -showdate \
 showformat -showformat \
+showgrid -showgrid \
 showlevel -showlevel \
 showltype -showltype \
 showmon -showmon \
@@ -632,6 +641,7 @@ strgal -strgal \
 strwin -strwin \
 sub -sub \
 subc -subc \
+subgrid -subgrid \
 subtrend -subtrend \
 szip -szip \
 tan -tan \
@@ -671,8 +681,10 @@ transxy -transxy \
 trend -trend \
 tstepcount -tstepcount \
 unsetgridmask -unsetgridmask \
+usegridnumber -usegridnumber \
 uv2dv -uv2dv \
 uv2dvl -uv2dvl \
+uvDestag -uvDestag \
 vardes -vardes \
 varquot2test -varquot2test \
 vct -vct \
@@ -696,6 +708,7 @@ vlist -vlist \
 wct -wct \
 writegrid -writegrid \
 writerandom -writerandom \
+xinfon -xinfon \
 ydayadd -ydayadd \
 ydayavg -ydayavg \
 ydaydiv -ydaydiv \
diff --git a/contrib/cdoCompletion.tcsh b/contrib/cdoCompletion.tcsh
index ce59c15..15ca8bb 100644
--- a/contrib/cdoCompletion.tcsh
+++ b/contrib/cdoCompletion.tcsh
@@ -56,6 +56,7 @@ boxavg \
 cat \
 cdiread \
 cdiwrite \
+changemulti \
 chcode \
 chlevel \
 chlevelc \
@@ -98,6 +99,9 @@ del29feb \
 delcode \
 delday \
 delete \
+delgridcell \
+delindex \
+delmulti \
 delname \
 delparam \
 deltap \
@@ -229,8 +233,6 @@ genlevelbounds \
 gennn \
 genycon \
 geopotheight \
-ggstat \
-ggstats \
 gheight \
 globavg \
 gmtcells \
@@ -436,6 +438,7 @@ pinfov \
 pow \
 pressure_fl \
 pressure_hl \
+projuvLatLon \
 random \
 reci \
 reducegrid \
@@ -458,6 +461,8 @@ remapycon \
 replace \
 retocomplex \
 rhopot \
+rotuvN \
+rotuvNorth \
 rotuvb \
 runavg \
 runmax \
@@ -469,6 +474,7 @@ runstd1 \
 runsum \
 runvar \
 runvar1 \
+samplegrid \
 scatter \
 sealevelpressure \
 seasavg \
@@ -492,6 +498,7 @@ seldate \
 selday \
 select \
 selgrid \
+selgridcell \
 selgridname \
 selhour \
 selindex \
@@ -502,6 +509,7 @@ sellonlatbox \
 selltype \
 selmon \
 selmonth \
+selmulti \
 selname \
 seloperator \
 selparam \
@@ -572,6 +580,7 @@ shifty \
 showcode \
 showdate \
 showformat \
+showgrid \
 showlevel \
 showltype \
 showmon \
@@ -632,6 +641,7 @@ strgal \
 strwin \
 sub \
 subc \
+subgrid \
 subtrend \
 szip \
 tan \
@@ -671,8 +681,10 @@ transxy \
 trend \
 tstepcount \
 unsetgridmask \
+usegridnumber \
 uv2dv \
 uv2dvl \
+uvDestag \
 vardes \
 varquot2test \
 vct \
@@ -696,6 +708,7 @@ vlist \
 wct \
 writegrid \
 writerandom \
+xinfon \
 ydayadd \
 ydayavg \
 ydaydiv \
diff --git a/contrib/cdoCompletion.zsh b/contrib/cdoCompletion.zsh
index 4698ad5..e7cd986 100644
--- a/contrib/cdoCompletion.zsh
+++ b/contrib/cdoCompletion.zsh
@@ -56,6 +56,7 @@ boxavg -boxavg \
 cat -cat \
 cdiread -cdiread \
 cdiwrite -cdiwrite \
+changemulti -changemulti \
 chcode -chcode \
 chlevel -chlevel \
 chlevelc -chlevelc \
@@ -98,6 +99,9 @@ del29feb -del29feb \
 delcode -delcode \
 delday -delday \
 delete -delete \
+delgridcell -delgridcell \
+delindex -delindex \
+delmulti -delmulti \
 delname -delname \
 delparam -delparam \
 deltap -deltap \
@@ -229,8 +233,6 @@ genlevelbounds -genlevelbounds \
 gennn -gennn \
 genycon -genycon \
 geopotheight -geopotheight \
-ggstat -ggstat \
-ggstats -ggstats \
 gheight -gheight \
 globavg -globavg \
 gmtcells -gmtcells \
@@ -436,6 +438,7 @@ pinfov -pinfov \
 pow -pow \
 pressure_fl -pressure_fl \
 pressure_hl -pressure_hl \
+projuvLatLon -projuvLatLon \
 random -random \
 reci -reci \
 reducegrid -reducegrid \
@@ -458,6 +461,8 @@ remapycon -remapycon \
 replace -replace \
 retocomplex -retocomplex \
 rhopot -rhopot \
+rotuvN -rotuvN \
+rotuvNorth -rotuvNorth \
 rotuvb -rotuvb \
 runavg -runavg \
 runmax -runmax \
@@ -469,6 +474,7 @@ runstd1 -runstd1 \
 runsum -runsum \
 runvar -runvar \
 runvar1 -runvar1 \
+samplegrid -samplegrid \
 scatter -scatter \
 sealevelpressure -sealevelpressure \
 seasavg -seasavg \
@@ -492,6 +498,7 @@ seldate -seldate \
 selday -selday \
 select -select \
 selgrid -selgrid \
+selgridcell -selgridcell \
 selgridname -selgridname \
 selhour -selhour \
 selindex -selindex \
@@ -502,6 +509,7 @@ sellonlatbox -sellonlatbox \
 selltype -selltype \
 selmon -selmon \
 selmonth -selmonth \
+selmulti -selmulti \
 selname -selname \
 seloperator -seloperator \
 selparam -selparam \
@@ -572,6 +580,7 @@ shifty -shifty \
 showcode -showcode \
 showdate -showdate \
 showformat -showformat \
+showgrid -showgrid \
 showlevel -showlevel \
 showltype -showltype \
 showmon -showmon \
@@ -632,6 +641,7 @@ strgal -strgal \
 strwin -strwin \
 sub -sub \
 subc -subc \
+subgrid -subgrid \
 subtrend -subtrend \
 szip -szip \
 tan -tan \
@@ -671,8 +681,10 @@ transxy -transxy \
 trend -trend \
 tstepcount -tstepcount \
 unsetgridmask -unsetgridmask \
+usegridnumber -usegridnumber \
 uv2dv -uv2dv \
 uv2dvl -uv2dvl \
+uvDestag -uvDestag \
 vardes -vardes \
 varquot2test -varquot2test \
 vct -vct \
@@ -696,6 +708,7 @@ vlist -vlist \
 wct -wct \
 writegrid -writegrid \
 writerandom -writerandom \
+xinfon -xinfon \
 ydayadd -ydayadd \
 ydayavg -ydayavg \
 ydaydiv -ydaydiv \
diff --git a/doc/cdo.pdf b/doc/cdo.pdf
index 62e5998..1ebc793 100644
Binary files a/doc/cdo.pdf and b/doc/cdo.pdf differ
diff --git a/doc/cdo_refcard.pdf b/doc/cdo_refcard.pdf
index 6c0a1dd..6d53552 100644
Binary files a/doc/cdo_refcard.pdf and b/doc/cdo_refcard.pdf differ
diff --git a/libcdi/ChangeLog b/libcdi/ChangeLog
index 94862ae..2c69a93 100644
--- a/libcdi/ChangeLog
+++ b/libcdi/ChangeLog
@@ -1,3 +1,58 @@
+2017-04-13  Uwe Schulzweida
+
+	* Version 1.8.1 released
+
+2017-04-12  Uwe Schulzweida
+
+	* file_fill_buffer: set offset (bug fix) [patch from Harald Anlauf]
+
+2017-04-10  Uwe Schulzweida
+
+	* gribapi: use keys iScansNegatively and jScansPositively
+
+2017-04-09  Uwe Schulzweida
+
+	* Refactor GRID_LCC to GRID_PROJECTION
+
+2017-04-05  Uwe Schulzweida
+
+	* Scalar Z-Coordinate: added support for bounds (bug fix)
+
+2017-03-18  Uwe Schulzweida
+
+	* grid_check_cyclic: check yvals for curvilinear grids (bug fix)
+
+2017-03-17  Uwe Schulzweida
+
+	* gridCompareSearch: change 3rd parameter of gridCompare() to true.
+
+2017-03-14  Uwe Schulzweida
+
+	* set chunk size of time axis to 512
+	* set min deflate size of data variables to 16
+	* streamOpenAppend: set defmiss = true (Needed for NetCDF4)
+
+2017-03-08  Uwe Schulzweida
+
+	* Preserve netcdf time units attribute
+
+2017-03-07  Uwe Schulzweida
+
+	* Added function streamGrbChangeParameterIdentification() (patch from Michal Koutek, KMNI)
+
+2017-02-27  Uwe Schulzweida
+
+	* Added function gridDefUvRelativeToGrid()
+	* gridInqUvRelativeToGrid(): added cgribex support
+
+2017-02-24  Uwe Schulzweida
+
+	* Added function gridInqUvRelativeToGrid() (patch from Michal Koutek, KMNI)
+
+2017-02-22  Uwe Schulzweida
+
+	* CDI_CHUNK_AUTO: set chunk_size_max to 65536
+
 2017-02-14  Uwe Schulzweida
 
         * using CGRIBEX library version 1.7.6
diff --git a/libcdi/Makefile.in b/libcdi/Makefile.in
index d48da22..a13b31c 100644
--- a/libcdi/Makefile.in
+++ b/libcdi/Makefile.in
@@ -108,6 +108,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/NEWS b/libcdi/NEWS
index 487f972..8bda3a1 100644
--- a/libcdi/NEWS
+++ b/libcdi/NEWS
@@ -1,7 +1,7 @@
 CDI NEWS
 --------
 
-Version 1.8.0 (26 October 2016):
+Version 1.8.0 (14 February 2017):
 
    New features:
      * Refactor horizontal and vertical grid module
diff --git a/libcdi/aclocal.m4 b/libcdi/aclocal.m4
index f7f2c3b..74a336f 100644
--- a/libcdi/aclocal.m4
+++ b/libcdi/aclocal.m4
@@ -1196,6 +1196,7 @@ m4_include([m4/acx_lang_package.m4])
 m4_include([m4/acx_lt_problems.m4])
 m4_include([m4/acx_option_search_libs.m4])
 m4_include([m4/acx_options.m4])
+m4_include([m4/acx_prog_cc_posix.m4])
 m4_include([m4/acx_sl_fc_mod_path_flag.m4])
 m4_include([m4/acx_sl_mod_suffix.m4])
 m4_include([m4/asx_tr_arg.m4])
diff --git a/libcdi/app/Makefile.in b/libcdi/app/Makefile.in
index bcaa36a..c5c9cad 100644
--- a/libcdi/app/Makefile.in
+++ b/libcdi/app/Makefile.in
@@ -101,6 +101,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/app/printinfo.h b/libcdi/app/printinfo.h
index f019c8e..e0fe4b4 100644
--- a/libcdi/app/printinfo.h
+++ b/libcdi/app/printinfo.h
@@ -226,7 +226,7 @@ void print_xyvals2D(int gridID, int dig)
           int xsize = gridInqXsize(gridID);
           if ( xsize > 1 )
             {
-              double *xvals = (double*) malloc(xsize*sizeof(double));
+              double *xvals = (double*) malloc((size_t)xsize*sizeof(double));
               for ( int i = 0; i < xsize; ++i ) xvals[i] = xvals2D[i];
               xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
               for ( int i = 2; i < xsize; i++ )
@@ -236,7 +236,7 @@ void print_xyvals2D(int gridID, int dig)
           int ysize = gridInqYsize(gridID);
           if ( ysize > 1 )
             {
-              double *yvals = (double*) malloc(ysize*sizeof(double));
+              double *yvals = (double*) malloc((size_t)ysize*sizeof(double));
               for ( int i = 0; i < ysize; ++i ) yvals[i] = yvals2D[i*xsize];
               yinc = fabs(yvals[ysize-1] - yvals[0])/(ysize-1);
               for ( int i = 2; i < ysize; i++ )
@@ -279,6 +279,10 @@ void printGridInfoKernel(int gridID, int index, bool lproj)
   // int prec     = gridInqPrec(gridID);
   // int dig = (prec == CDI_DATATYPE_FLT64) ? 15 : 7;
   int dig = 7;
+#ifdef CDO
+  extern int CDO_flt_digits;
+  dig = CDO_flt_digits;
+#endif
 
   if ( !lproj )
     {
@@ -406,27 +410,6 @@ void printGridInfoKernel(int gridID, int index, bool lproj)
 
       print_xyvals2D(gridID, dig);
     }
-  else if ( gridtype == GRID_LCC )
-    {
-      double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
-      int projflag, scanflag;
-
-      gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                 &projflag, &scanflag);
-
-#ifdef CDO
-      set_text_color(stdout, RESET, GREEN);
-#endif
-      fprintf(stdout, "points=%d (%dx%d)  ", gridsize, xsize, ysize);
-      if ( (projflag&128) == 0 )
-        fprintf(stdout, "North Pole\n");
-      else
-        fprintf(stdout, "South Pole\n");
-      my_reset_text_color(stdout);
-
-      fprintf(stdout, "%33s : originLon=%g  originLat=%g  lonParY=%g\n", " ", originLon, originLat, lonParY);
-      fprintf(stdout, "%33s : lat1=%g  lat2=%g  xinc=%g m  yinc=%g m\n", " ", lat1, lat2, xincm, yincm);
-    }
   else /* if ( gridtype == GRID_GENERIC ) */
     {
 #ifdef CDO
@@ -439,7 +422,7 @@ void printGridInfoKernel(int gridID, int index, bool lproj)
       my_reset_text_color(stdout);
     }
 
-  if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC )
+  if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
     {
       if ( gridHasArea(gridID) ||
            gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
@@ -495,6 +478,10 @@ void printZaxisInfo(int vlistID)
       // int prec      = zaxisInqPrec(zaxisID);
       // int dig = (prec == CDI_DATATYPE_FLT64) ? 15 : 7;
       int dig = 7;
+#ifdef CDO
+      extern int CDO_flt_digits;
+      dig = CDO_flt_digits;
+#endif
 
       zaxisName(zaxistype, zaxisname);
       zaxisInqName(zaxisID, zname);
diff --git a/libcdi/cdi.settings.in b/libcdi/cdi.settings.in
index a53f5fc..b4d2c67 100644
--- a/libcdi/cdi.settings.in
+++ b/libcdi/cdi.settings.in
@@ -47,9 +47,6 @@
       "grib_api" : {
         "lib"      : "@GRIB_API_LIBS@",
         "include"  : "@GRIB_API_INCLUDE@"
-      },
-      "jasper" : {
-        "lib"      : "@JASPER_LIBS@"
       }
     }
   },
diff --git a/libcdi/configure b/libcdi/configure
index 4129851..896321c 100755
--- a/libcdi/configure
+++ b/libcdi/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for cdi 1.8.0.
+# Generated by GNU Autoconf 2.68 for cdi 1.8.1.
 #
 # Report bugs to <http://mpimet.mpg.de/cdi>.
 #
@@ -570,8 +570,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='cdi'
 PACKAGE_TARNAME='cdi'
-PACKAGE_VERSION='1.8.0'
-PACKAGE_STRING='cdi 1.8.0'
+PACKAGE_VERSION='1.8.1'
+PACKAGE_STRING='cdi 1.8.1'
 PACKAGE_BUGREPORT='http://mpimet.mpg.de/cdi'
 PACKAGE_URL=''
 
@@ -674,6 +674,8 @@ MPI_C_INCLUDE
 MPIROOT
 ENABLE_NETCDF_FALSE
 ENABLE_NETCDF_TRUE
+ENABLE_HIRLAM_EXTENSIONS_FALSE
+ENABLE_HIRLAM_EXTENSIONS_TRUE
 ENABLE_ALL_STATIC_FALSE
 ENABLE_ALL_STATIC_TRUE
 ENABLE_CDI_LIB
@@ -865,6 +867,7 @@ enable_service
 enable_extra
 enable_ieg
 enable_all_static
+enable_hirlam_extensions
 enable_mpi
 with_mpi_root
 with_mpi_include
@@ -1460,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures cdi 1.8.0 to adapt to many kinds of systems.
+\`configure' configures cdi 1.8.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1530,7 +1533,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of cdi 1.8.0:";;
+     short | recursive ) echo "Configuration of cdi 1.8.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1560,6 +1563,8 @@ Optional Features:
   --enable-ieg            Use the ieg library [default=yes]
   --enable-all-static     build a completely statically linked CDO binary
                           [default=no]
+  --enable-hirlam-extensions
+                          HIRLAM extensions [default=no]
   --enable-mpi            Compile with MPI compiler [default=no]
   --enable-iso-c-interface
                           Create Fortran Interface via iso_c_bindings facility
@@ -1723,7 +1728,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-cdi configure 1.8.0
+cdi configure 1.8.1
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2568,7 +2573,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by cdi $as_me 1.8.0, which was
+It was created by cdi $as_me 1.8.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3520,7 +3525,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='cdi'
- VERSION='1.8.0'
+ VERSION='1.8.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -4949,6 +4954,54 @@ fi
 
 
 
+acx_prog_cc_posix_version_value=200112
+             acx_prog_cc_posix_version_print="POSIX.1-2001"
+   ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking For conformance to ${acx_prog_cc_posix_version_print}." >&5
+$as_echo_n "checking For conformance to ${acx_prog_cc_posix_version_print}.... " >&6; }
+if ${acx_cv_cc_posix_support2001+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <unistd.h>
+int
+main ()
+{
+  int n[(_POSIX_VERSION >= ${acx_prog_cc_posix_version_value}L) * 2 - 1];
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  acx_cv_cc_posix_support2001=yes
+else
+  acx_cv_cc_posix_support2001=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_cc_posix_support2001" >&5
+$as_echo "$acx_cv_cc_posix_support2001" >&6; }
+   if test "x$acx_cv_cc_posix_support2001" = xno; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: It seems your system does not define _POSIX_VERSION to a value
+greater-or-equal ${acx_prog_cc_posix_version_value}. This is typically the case when the
+compiler is instructed to make ISO C features available only,
+e.g. when using gcc -std=c99" >&5
+$as_echo "$as_me: It seems your system does not define _POSIX_VERSION to a value
+greater-or-equal ${acx_prog_cc_posix_version_value}. This is typically the case when the
+compiler is instructed to make ISO C features available only,
+e.g. when using gcc -std=c99" >&6;}
+      { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "${acx_prog_cc_posix_version_print} profile required
+See \`config.log' for more details" "$LINENO" 5; }
+fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
 $as_echo_n "checking for C/C++ restrict keyword... " >&6; }
@@ -23389,7 +23442,7 @@ Usage: $0 [OPTIONS]
 Report bugs to <bug-libtool at gnu.org>."
 
 lt_cl_version="\
-cdi config.lt 1.8.0
+cdi config.lt 1.8.1
 configured by $0, generated by GNU Autoconf 2.68.
 
 Copyright (C) 2011 Free Software Foundation, Inc.
@@ -27877,6 +27930,35 @@ else
   ENABLE_ALL_STATIC_FALSE=
 fi
 
+#  ----------------------------------------------------------------------
+#  Build CDO with HIRLAM extensions
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HIRLAM extensions" >&5
+$as_echo_n "checking for HIRLAM extensions... " >&6; }
+# Check whether --enable-hirlam-extensions was given.
+if test "${enable_hirlam_extensions+set}" = set; then :
+  enableval=$enable_hirlam_extensions; if test "x$enable_hirlam_extensions" != "xno"; then :
+
+$as_echo "#define HIRLAM_EXTENSIONS 1" >>confdefs.h
+
+                     enable_hirlam_extensions=yes
+else
+  enable_hirlam_extensions=no
+fi
+else
+  enable_hirlam_extensions=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_hirlam_extensions" >&5
+$as_echo "$enable_hirlam_extensions" >&6; }
+ if test x$enable_hirlam_extensions = 'xyes'; then
+  ENABLE_HIRLAM_EXTENSIONS_TRUE=
+  ENABLE_HIRLAM_EXTENSIONS_FALSE='#'
+else
+  ENABLE_HIRLAM_EXTENSIONS_TRUE='#'
+  ENABLE_HIRLAM_EXTENSIONS_FALSE=
+fi
+
+#
 
  if test x$ENABLE_NETCDF = xyes; then
   ENABLE_NETCDF_TRUE=
@@ -30073,6 +30155,10 @@ if test -z "${ENABLE_ALL_STATIC_TRUE}" && test -z "${ENABLE_ALL_STATIC_FALSE}";
   as_fn_error $? "conditional \"ENABLE_ALL_STATIC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${ENABLE_HIRLAM_EXTENSIONS_TRUE}" && test -z "${ENABLE_HIRLAM_EXTENSIONS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_HIRLAM_EXTENSIONS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${ENABLE_NETCDF_TRUE}" && test -z "${ENABLE_NETCDF_FALSE}"; then
   as_fn_error $? "conditional \"ENABLE_NETCDF\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -30534,7 +30620,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by cdi $as_me 1.8.0, which was
+This file was extended by cdi $as_me 1.8.1, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -30600,7 +30686,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-cdi config.status 1.8.0
+cdi config.status 1.8.1
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
diff --git a/libcdi/configure.ac b/libcdi/configure.ac
index 63bedad..8ffba06 100644
--- a/libcdi/configure.ac
+++ b/libcdi/configure.ac
@@ -4,7 +4,7 @@
 #  autoconf 2.68
 #  libtool  2.4.2
 
-AC_INIT([cdi], [1.8.0], [http://mpimet.mpg.de/cdi])
+AC_INIT([cdi], [1.8.1], [http://mpimet.mpg.de/cdi])
 
 AC_DEFINE_UNQUOTED(CDI, ["$PACKAGE_VERSION"], [CDI version])
 
@@ -26,6 +26,8 @@ AM_MAINTAINER_MODE([disable])
 # Check building environment
 AC_CHECK_TOOL([CC],[gcc],[:])
 AC_PROG_CC_C99
+dnl verify the setup supports POSIX 2001
+ACX_PROG_CC_POSIX([2001])
 AM_PROG_CC_C_O
 AC_C_RESTRICT
 AC_PROG_FC
diff --git a/libcdi/examples/Makefile.in b/libcdi/examples/Makefile.in
index 906edca..6852069 100644
--- a/libcdi/examples/Makefile.in
+++ b/libcdi/examples/Makefile.in
@@ -101,6 +101,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/examples/pio/Makefile.in b/libcdi/examples/pio/Makefile.in
index 5f27b58..cb52b11 100644
--- a/libcdi/examples/pio/Makefile.in
+++ b/libcdi/examples/pio/Makefile.in
@@ -102,6 +102,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/examples/pio/compareResourcesArray.c b/libcdi/examples/pio/compareResourcesArray.c
index 6d359f0..297d808 100644
--- a/libcdi/examples/pio/compareResourcesArray.c
+++ b/libcdi/examples/pio/compareResourcesArray.c
@@ -58,14 +58,7 @@ static int defineGrid()
   gridDefYlongname ( gridID, "myYlongname" );
   gridDefYunits ( gridID, "myYunits" );
   gridDefPrec ( gridID, DOUBLE_PRECISION );
-  gridDefXpole ( gridID, 90.0 );
-  gridDefYpole ( gridID, 180.0 );
-  gridDefAngle ( gridID, 360.0 );
   gridDefTrunc ( gridID, 1 );
-  gridDefGMEnd ( gridID, 2 );
-  gridDefGMEni ( gridID, 3 );
-  gridDefGMEni2 ( gridID, 4 );
-  gridDefGMEni3 ( gridID, 5 );
   gridDefNumber ( gridID, 6 );
   gridDefPosition ( gridID, 7 );
   gridDefReference ( gridID, "myReference" );
@@ -146,11 +139,11 @@ static int defineVlist ( int gridID, int zaxisID, int taxisID )
   vlistDefVarName(vlistID, varID1, "varname1");
   {
     int globfac[] = { 23, 42 };
-    vlistDefAttInt(vlistID, varID1, "seer's globule factors", CDI_DATATYPE_INT16,
+    cdiDefAttInt(vlistID, varID1, "seer's globule factors", CDI_DATATYPE_INT16,
                    2, globfac);
   }
   vlistDefVarName(vlistID, varID2, "varname2");
-  vlistDefAttTxt(vlistID, varID2, "txt demo", 6, "banana");
+  cdiDefAttTxt(vlistID, varID2, "txt demo", 6, "banana");
   vlistDefTaxis(vlistID, taxisID);
   return vlistID;
 }
diff --git a/libcdi/interfaces/Makefile.in b/libcdi/interfaces/Makefile.in
index 49bc178..f52e8ec 100644
--- a/libcdi/interfaces/Makefile.in
+++ b/libcdi/interfaces/Makefile.in
@@ -108,6 +108,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/m4/acx_options.m4 b/libcdi/m4/acx_options.m4
index 58ca0f4..44fe876 100644
--- a/libcdi/m4/acx_options.m4
+++ b/libcdi/m4/acx_options.m4
@@ -266,6 +266,19 @@ AC_ARG_ENABLE([all-static],
               [enable_all_static=no])
 AC_MSG_RESULT([$enable_all_static])
 AM_CONDITIONAL([ENABLE_ALL_STATIC],[test x$enable_all_static = 'xyes'])
+#  ----------------------------------------------------------------------
+#  Build CDO with HIRLAM extensions
+AC_MSG_CHECKING([for HIRLAM extensions])
+AC_ARG_ENABLE([hirlam-extensions],
+              [AS_HELP_STRING([--enable-hirlam-extensions],[HIRLAM extensions [default=no]])],
+              [AS_IF([test "x$enable_hirlam_extensions" != "xno"],
+                    [AC_DEFINE(HIRLAM_EXTENSIONS,[1],[Define to 1 for HIRLAM extensions])
+                     enable_hirlam_extensions=yes],
+                    [enable_hirlam_extensions=no])],
+              [enable_hirlam_extensions=no])
+AC_MSG_RESULT([$enable_hirlam_extensions])
+AM_CONDITIONAL([ENABLE_HIRLAM_EXTENSIONS],[test x$enable_hirlam_extensions = 'xyes'])
+#
 ])
 dnl
 dnl Local Variables:
diff --git a/libcdi/m4/acx_prog_cc_posix.m4 b/libcdi/m4/acx_prog_cc_posix.m4
new file mode 100644
index 0000000..fc3a37f
--- /dev/null
+++ b/libcdi/m4/acx_prog_cc_posix.m4
@@ -0,0 +1,71 @@
+dnl acx_prog_cc_posix.m4 --- test whether _POSIX_VERSION is defined
+dnl
+dnl Copyright  (C)  2017  Thomas Jahns <jahns at dkrz.de>
+dnl
+dnl Version: 1.0
+dnl Keywords:
+dnl Author: Thomas Jahns <jahns at dkrz.de>
+dnl Maintainer: Thomas Jahns <jahns at dkrz.de>
+dnl URL: https://www.dkrz.de/redmine/projects/show/scales-ppm
+dnl
+dnl Redistribution and use in source and binary forms, with or without
+dnl modification, are  permitted provided that the following conditions are
+dnl met:
+dnl
+dnl Redistributions of source code must retain the above copyright notice,
+dnl this list of conditions and the following disclaimer.
+dnl
+dnl Redistributions in binary form must reproduce the above copyright
+dnl notice, this list of conditions and the following disclaimer in the
+dnl documentation and/or other materials provided with the distribution.
+dnl
+dnl Neither the name of the DKRZ GmbH nor the names of its contributors
+dnl may be used to endorse or promote products derived from this software
+dnl without specific prior written permission.
+dnl
+dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+dnl IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+dnl TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+dnl PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+dnl OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+dnl EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+dnl PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+dnl PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+dnl LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+dnl NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+dnl SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+dnl
+dnl ACX_PROG_CC_POSIX([VERSION])
+dnl Test if compiler is defining _POSIX_VERSION correctly to at least
+dnl the numeral corresponding to VERSION. Supported values for
+dnl version:
+dnl     1988, 1990, 1996, 2001, 2008
+dnl
+AC_DEFUN([ACX_PROG_CC_POSIX],
+  [m4_case([$1],
+     [1988],[acx_prog_cc_posix_version_value=198808
+             acx_prog_cc_posix_version_print="POSIX.1-1988"],
+     [1990],[acx_prog_cc_posix_version_value=199009
+             acx_prog_cc_posix_version_print="POSIX.1-1990"],
+     [1996],[acx_prog_cc_posix_version_value=199506L
+             acx_prog_cc_posix_version_print="POSIX.1-1996"],
+     [2001],[acx_prog_cc_posix_version_value=200112
+             acx_prog_cc_posix_version_print="POSIX.1-2001"],
+     [2008],[acx_prog_cc_posix_version_value=200809
+             acx_prog_cc_posix_version_print="POSIX.1-2008"],
+     [m4_fatal([Unexpected POSIX version argument])])
+   AC_LANG_PUSH([C])
+   AS_VAR_PUSHDEF([acx_cv_cc_posix_support],[acx_cv_cc_posix_support]$1)
+   AC_CACHE_CHECK([For conformance to ${acx_prog_cc_posix_version_print}.],
+     [acx_cv_cc_posix_support],
+     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <unistd.h>],
+        [  int n@<:@(_POSIX_VERSION >= ${acx_prog_cc_posix_version_value}L) * 2 - 1@:>@;])],
+        [AS_VAR_SET([acx_cv_cc_posix_support],[yes])],
+        [AS_VAR_SET([acx_cv_cc_posix_support],[no])])])
+   AS_VAR_IF([acx_cv_cc_posix_support],[no],
+     [AC_MSG_NOTICE(
+[It seems your system does not define _POSIX_VERSION to a value
+greater-or-equal ${acx_prog_cc_posix_version_value}. This is typically the case when the
+compiler is instructed to make ISO C features available only,
+e.g. when using gcc -std=c99])
+      AC_MSG_FAILURE([${acx_prog_cc_posix_version_print} profile required])])])
diff --git a/libcdi/src/Makefile.in b/libcdi/src/Makefile.in
index be115a8..8d724bd 100644
--- a/libcdi/src/Makefile.in
+++ b/libcdi/src/Makefile.in
@@ -117,6 +117,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/src/binary.h b/libcdi/src/binary.h
index 26a0a6d..f76f721 100644
--- a/libcdi/src/binary.h
+++ b/libcdi/src/binary.h
@@ -1,5 +1,5 @@
-#ifndef _BINARY_H
-#define _BINARY_H
+#ifndef BINARY_H
+#define BINARY_H
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
@@ -41,7 +41,7 @@ int binReadFlt64(int fileID, int byteswap, size_t size, FLT64 *ptr);
 int binWriteFlt32(int fileID, int byteswap, size_t size, FLT32 *ptr);
 int binWriteFlt64(int fileID, int byteswap, size_t size, FLT64 *ptr);
 
-#endif  /* _BINARY_H */
+#endif  /* BINARY_H */
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/calendar.c b/libcdi/src/calendar.c
index a40a65c..8ade92a 100644
--- a/libcdi/src/calendar.c
+++ b/libcdi/src/calendar.c
@@ -7,9 +7,9 @@
 #include "timebase.h"
 
 
-static int month_360[12] = {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30};
-static int month_365[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-static int month_366[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static const int month_360[12] = {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30};
+static const int month_365[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static const int month_366[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
 
 int calendar_dpy(int calendar)
@@ -26,9 +26,9 @@ int calendar_dpy(int calendar)
 
 int days_per_month(int calendar, int year, int month)
 {
-  int *dpm = NULL;
   int daysperyear = calendar_dpy(calendar);
 
+  const int *dpm;
   if      ( daysperyear == 360 ) dpm = month_360;
   else if ( daysperyear == 365 ) dpm = month_365;
   else                           dpm = month_366;
@@ -73,11 +73,11 @@ int days_per_year(int calendar, int year)
 static void decode_day(int dpy, int days, int *year, int *month, int *day)
 {
   int i = 0;
-  int *dpm = NULL;
 
   *year = (days-1) / dpy;
   days -= (*year*dpy);
 
+  const int *dpm = NULL;
   if      ( dpy == 360 ) dpm = month_360;
   else if ( dpy == 365 ) dpm = month_365;
   else if ( dpy == 366 ) dpm = month_366;
@@ -96,9 +96,9 @@ static void decode_day(int dpy, int days, int *year, int *month, int *day)
 
 static int encode_day(int dpy, int year, int month, int day)
 {
-  int *dpm = NULL;
   long rval = (long)dpy * year + day;
 
+  const int *dpm = NULL;
   if      ( dpy == 360 ) dpm = month_360;
   else if ( dpy == 365 ) dpm = month_365;
   else if ( dpy == 366 ) dpm = month_366;
diff --git a/libcdi/src/cdf_int.c b/libcdi/src/cdf_int.c
index 65f83e8..cfc3574 100644
--- a/libcdi/src/cdf_int.c
+++ b/libcdi/src/cdf_int.c
@@ -771,6 +771,15 @@ void cdf_inq_attid(int ncid, int varid, const char *name, int *attnump)
   if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
 }
 
+
+#if  defined  (HAVE_NETCDF4)
+void cdf_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp)
+{
+  int status = nc_def_var_chunking(ncid, varid, storage, chunksizesp);
+  if ( status != NC_NOERR ) Error("%s", nc_strerror(status));
+}
+#endif
+
 #endif
 /*
  * Local Variables:
diff --git a/libcdi/src/cdf_int.h b/libcdi/src/cdf_int.h
index 91de788..d4dfd0f 100644
--- a/libcdi/src/cdf_int.h
+++ b/libcdi/src/cdf_int.h
@@ -85,6 +85,8 @@ void cdf_inq_attlen (int ncid, int varid, const char *name, size_t *lenp);
 void cdf_inq_attname(int ncid, int varid, int attnum, char *name);
 void cdf_inq_attid  (int ncid, int varid, const char *name, int *attnump);
 
+void cdf_def_var_chunking(int ncid, int varid, int storage, const size_t *chunksizesp);
+
 typedef int (*cdi_nc__create_funcp)(const char *path, int cmode,
                                     size_t initialsz, size_t *chunksizehintp,
                                     int *ncidp);
diff --git a/libcdi/src/cdf_lazy_grid.c b/libcdi/src/cdf_lazy_grid.c
index 37bdabd..d287df2 100644
--- a/libcdi/src/cdf_lazy_grid.c
+++ b/libcdi/src/cdf_lazy_grid.c
@@ -2,6 +2,7 @@
 #include "config.h"
 #endif
 
+#ifdef HAVE_LIBNETCDF
 #include "stream_cdf.h"
 #include "cdf_lazy_grid.h"
 
@@ -28,7 +29,6 @@ static bool cdfLazyInitialized;
 #endif
 
 
-#ifdef HAVE_LIBNETCDF
 
 void cdfLazyGridDestroy(struct cdfLazyGrid *lazyGrid)
 {
diff --git a/libcdi/src/cdf_util.c b/libcdi/src/cdf_util.c
index 5ed8afa..c0a93e7 100644
--- a/libcdi/src/cdf_util.c
+++ b/libcdi/src/cdf_util.c
@@ -94,14 +94,11 @@ bool is_timeaxis_units(const char *timeunits)
 
 bool is_height_units(const char *units)
 {
-  bool status = false;
   int u0 = units[0];
 
-  if ( (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0)) ||
-       (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k')) )
-    {
-      status = true;
-    }
+  bool status
+    = (u0=='m' && (!units[1] || strncmp(units, "meter", 5) == 0))
+    || (!units[2] && units[1]=='m' && (u0=='c' || u0=='d' || u0=='k'));
 
   return status;
 }
@@ -192,9 +189,9 @@ bool is_lon_axis(const char *units, const char *stdname)
     {
       status = true;
     }
-
-  if ( status == false && str_is_equal(lc_units, "degree") &&
-       !str_is_equal(stdname, "grid_latitude") && !str_is_equal(stdname, "latitude") )
+  else if ( str_is_equal(lc_units, "degree")
+            && !str_is_equal(stdname, "grid_latitude")
+            && !str_is_equal(stdname, "latitude") )
     {
       int ioff = 6;
       if ( lc_units[ioff] == 's' ) ioff++;
@@ -220,9 +217,9 @@ bool is_lat_axis(const char *units, const char *stdname)
     {
       status = true;
     }
-
-  if ( status == false && str_is_equal(lc_units, "degree") &&
-       !str_is_equal(stdname, "grid_longitude") && !str_is_equal(stdname, "longitude") )
+  else if ( str_is_equal(lc_units, "degree")
+            && !str_is_equal(stdname, "grid_longitude")
+            && !str_is_equal(stdname, "longitude") )
     {
       int ioff = 6;
       if ( lc_units[ioff] == 's' ) ioff++;
diff --git a/libcdi/src/cdf_write.c b/libcdi/src/cdf_write.c
index 8d94bff..7ee19b6 100644
--- a/libcdi/src/cdf_write.c
+++ b/libcdi/src/cdf_write.c
@@ -327,7 +327,6 @@ int cdfDefVar(stream_t *streamptr, int varID)
   size_t iax = 0;
   char axis[5];
   int ensID, ensCount, forecast_type;
-  int retval;
 
   int fileID  = streamptr->fileID;
 
@@ -350,8 +349,8 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   vlistInqVarDimorder(vlistID, varID, &dimorder);
 
-  int gridsize  = gridInqSize(gridID);
-  bool lchunk = (gridsize > 1);
+  size_t gridsize  = (size_t)(gridInqSize(gridID));
+  bool lchunk = (gridsize >= 16);
   int gridtype  = gridInqType(gridID);
   int gridindex = nc_grid_index(streamptr, gridID);
   if ( gridtype != GRID_TRAJECTORY )
@@ -395,6 +394,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
   if ( xid != CDI_UNDEFID ) chunks[ndims] = xsize;
   if ( xid != CDI_UNDEFID ) dims[ndims++] = xid;
   */
+  size_t chunk_size_max = 65536;
   for ( int id = 0; id < 3; ++id )
     {
       if ( dimorder[id] == 3 && zid != CDI_UNDEFID )
@@ -406,16 +406,19 @@ int cdfDefVar(stream_t *streamptr, int varID)
         }
       else if ( dimorder[id] == 2 && yid != CDI_UNDEFID )
         {
-          if ( chunktype == CDI_CHUNK_LINES )
-            chunks[ndims] = 1;
+          if ( chunktype == CDI_CHUNK_AUTO )
+            chunks[ndims] = (chunk_size_max > gridsize) ? ysize : chunk_size_max/xsize;
           else
-            chunks[ndims] = ysize;
+            chunks[ndims] = (chunktype == CDI_CHUNK_LINES) ? 1 : ysize;
           dims[ndims] = yid;
           ndims++;
         }
       else if ( dimorder[id] == 1 && xid != CDI_UNDEFID )
         {
-          chunks[ndims] = xsize;
+          if ( chunktype == CDI_CHUNK_AUTO && yid == CDI_UNDEFID )
+            chunks[ndims] = (chunk_size_max > xsize) ? xsize : chunk_size_max;
+          else
+            chunks[ndims] = xsize;
           dims[ndims] = xid;
           ndims++;
         }
@@ -504,14 +507,7 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
 #if  defined  (HAVE_NETCDF4)
   if ( lchunk && (streamptr->filetype == CDI_FILETYPE_NC4 || streamptr->filetype == CDI_FILETYPE_NC4C) )
-    {
-      if ( chunktype == CDI_CHUNK_AUTO )
-        retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
-      else
-        retval = nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
-
-      if ( retval ) Error("nc_def_var_chunking failed, status = %d", retval);
-    }
+    cdf_def_var_chunking(fileID, ncvarid, NC_CHUNKED, chunks);
 #endif
 
   if ( streamptr->comptype == CDI_COMPRESS_ZIP )
@@ -656,14 +652,12 @@ int cdfDefVar(stream_t *streamptr, int varID)
 
   /*  if ( xtype == NC_BYTE || xtype == NC_SHORT || xtype == NC_INT ) */
     {
-      int laddoffset, lscalefactor;
-      double addoffset, scalefactor;
       int astype = NC_DOUBLE;
 
-      addoffset    = vlistInqVarAddoffset(vlistID, varID);
-      scalefactor  = vlistInqVarScalefactor(vlistID, varID);
-      laddoffset   = IS_NOT_EQUAL(addoffset, 0);
-      lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
+      double addoffset   = vlistInqVarAddoffset(vlistID, varID);
+      double scalefactor = vlistInqVarScalefactor(vlistID, varID);
+      bool laddoffset   = IS_NOT_EQUAL(addoffset, 0);
+      bool lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
 
       if ( laddoffset || lscalefactor )
         {
@@ -960,8 +954,7 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
   size_t start[5];
   size_t count[5];
   bool swapxy = false;
-  int ndims = 0;
-  int idim;
+  size_t ndims = 0;
 
   if ( CDI_Debug ) Message("streamID = %d  varID = %d", streamptr->self, varID);
 
@@ -1027,7 +1020,7 @@ void cdf_write_var(stream_t *streamptr, int varID, int memtype, const void *data
     }
 
   if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
+    for (size_t idim = 0; idim < ndims; idim++)
       Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
 
   if ( streamptr->ncmode == 1 )
@@ -1056,8 +1049,7 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
   size_t start[5];
   size_t count[5];
   bool swapxy = false;
-  int ndims = 0;
-  int idim;
+  size_t ndims = 0;
   int streamID = streamptr->self;
 
   if ( CDI_Debug )
@@ -1129,7 +1121,7 @@ void cdf_write_var_chunk(stream_t *streamptr, int varID, int memtype,
     }
 
   if ( CDI_Debug )
-    for (idim = 0; idim < ndims; idim++)
+    for (size_t idim = 0; idim < ndims; idim++)
       Message("dim = %d  start = %d  count = %d", idim, start[idim], count[idim]);
 
   if ( streamptr->ncmode == 1 )
diff --git a/libcdi/src/cdi.h b/libcdi/src/cdi.h
index c9cc8cb..67a378c 100644
--- a/libcdi/src/cdi.h
+++ b/libcdi/src/cdi.h
@@ -932,8 +932,8 @@ void    gridDefParamGME(int gridID, int nd, int ni, int ni2, int ni3);
 void    gridInqParamGME(int gridID, int *nd, int *ni, int *ni2, int *ni3);
 
   /* Lambert Conformal Conic grid (GRIB version) */
-void    gridDefParamLCC(int gridID, double originLon, double originLat, double lonParY, double lat1, double lat2, double xinc, double yinc, int projflag, int scanflag);
-void    gridInqParamLCC(int gridID, double *originLon, double *originLat, double *lonParY, double *lat1, double *lat2, double *xinc, double *yinc, int *projflag, int *scanflag);
+void gridDefParamLCC(int gridID, double missval, double lon_0, double lat_0, double lat_1, double lat_2, double a, double rf, double xval_0, double yval_0, double x_0, double y_0);
+int gridInqParamLCC(int gridID, double missval, double *lon_0, double *lat_0, double *lat_1, double *lat_2, double *a, double *rf, double *xval_0, double *yval_0, double *x_0, double *y_0);
 
 void    gridDefArea(int gridID, const double area[]);
 void    gridInqArea(int gridID, double area[]);
@@ -964,6 +964,12 @@ void    gridChangeType(int gridID, int gridtype);
 void    gridDefComplexPacking(int gridID, int lpack);
 int     gridInqComplexPacking(int gridID);
 
+void    gridDefUvRelativeToGrid(int gridID, int uvRelativeToGrid);
+int     gridInqUvRelativeToGrid(int gridID);
+
+void    gridDefScanningMode(int gridID, int mode);
+int     gridInqScanningMode(int gridID);
+
 /* ZAXIS routines */
 
 void    zaxisName(int zaxistype, char *zaxisname);
diff --git a/libcdi/src/cdi.inc b/libcdi/src/cdi.inc
index 103b388..8be02f8 100644
--- a/libcdi/src/cdi.inc
+++ b/libcdi/src/cdi.inc
@@ -1,341 +1,341 @@
 ! This file was automatically generated, don't edit!
 !
-! Fortran interface for CDI library version 1.8.0
+! Fortran interface for CDI library version 1.8.1
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   February 2017
+! Uwe Schulzweida, MPI-MET, Hamburg,   April 2017
 !
 
-      INTEGER    CDI_MAX_NAME          
+      INTEGER    CDI_MAX_NAME
       PARAMETER (CDI_MAX_NAME           = 256)
-      INTEGER    CDI_UNDEFID           
+      INTEGER    CDI_UNDEFID
       PARAMETER (CDI_UNDEFID            = -1)
-      INTEGER    CDI_GLOBAL            
+      INTEGER    CDI_GLOBAL
       PARAMETER (CDI_GLOBAL             = -1)
 !
 !  Byte order
 !
-      INTEGER    CDI_BIGENDIAN         
+      INTEGER    CDI_BIGENDIAN
       PARAMETER (CDI_BIGENDIAN          =  0)
-      INTEGER    CDI_LITTLEENDIAN      
+      INTEGER    CDI_LITTLEENDIAN
       PARAMETER (CDI_LITTLEENDIAN       =  1)
-      INTEGER    CDI_PDPENDIAN         
+      INTEGER    CDI_PDPENDIAN
       PARAMETER (CDI_PDPENDIAN          =  2)
-      INTEGER    CDI_REAL              
+      INTEGER    CDI_REAL
       PARAMETER (CDI_REAL               =  1)
-      INTEGER    CDI_COMP              
+      INTEGER    CDI_COMP
       PARAMETER (CDI_COMP               =  2)
-      INTEGER    CDI_BOTH              
+      INTEGER    CDI_BOTH
       PARAMETER (CDI_BOTH               =  3)
 !
 !  Error identifier
 !
-      INTEGER    CDI_NOERR             
+      INTEGER    CDI_NOERR
       PARAMETER (CDI_NOERR              =  0)
-      INTEGER    CDI_EEOF              
+      INTEGER    CDI_EEOF
       PARAMETER (CDI_EEOF               = -1)
-      INTEGER    CDI_ESYSTEM           
+      INTEGER    CDI_ESYSTEM
       PARAMETER (CDI_ESYSTEM            = -10)
-      INTEGER    CDI_EINVAL            
+      INTEGER    CDI_EINVAL
       PARAMETER (CDI_EINVAL             = -20)
-      INTEGER    CDI_EUFTYPE           
+      INTEGER    CDI_EUFTYPE
       PARAMETER (CDI_EUFTYPE            = -21)
-      INTEGER    CDI_ELIBNAVAIL        
+      INTEGER    CDI_ELIBNAVAIL
       PARAMETER (CDI_ELIBNAVAIL         = -22)
-      INTEGER    CDI_EUFSTRUCT         
+      INTEGER    CDI_EUFSTRUCT
       PARAMETER (CDI_EUFSTRUCT          = -23)
-      INTEGER    CDI_EUNC4             
+      INTEGER    CDI_EUNC4
       PARAMETER (CDI_EUNC4              = -24)
-      INTEGER    CDI_ELIMIT            
+      INTEGER    CDI_ELIMIT
       PARAMETER (CDI_ELIMIT             = -99)
 !
 !  File types
 !
-      INTEGER    CDI_FILETYPE_GRB      
+      INTEGER    CDI_FILETYPE_GRB
       PARAMETER (CDI_FILETYPE_GRB       =  1)
-      INTEGER    CDI_FILETYPE_GRB2     
+      INTEGER    CDI_FILETYPE_GRB2
       PARAMETER (CDI_FILETYPE_GRB2      =  2)
-      INTEGER    CDI_FILETYPE_NC       
+      INTEGER    CDI_FILETYPE_NC
       PARAMETER (CDI_FILETYPE_NC        =  3)
-      INTEGER    CDI_FILETYPE_NC2      
+      INTEGER    CDI_FILETYPE_NC2
       PARAMETER (CDI_FILETYPE_NC2       =  4)
-      INTEGER    CDI_FILETYPE_NC4      
+      INTEGER    CDI_FILETYPE_NC4
       PARAMETER (CDI_FILETYPE_NC4       =  5)
-      INTEGER    CDI_FILETYPE_NC4C     
+      INTEGER    CDI_FILETYPE_NC4C
       PARAMETER (CDI_FILETYPE_NC4C      =  6)
-      INTEGER    CDI_FILETYPE_SRV      
+      INTEGER    CDI_FILETYPE_SRV
       PARAMETER (CDI_FILETYPE_SRV       =  7)
-      INTEGER    CDI_FILETYPE_EXT      
+      INTEGER    CDI_FILETYPE_EXT
       PARAMETER (CDI_FILETYPE_EXT       =  8)
-      INTEGER    CDI_FILETYPE_IEG      
+      INTEGER    CDI_FILETYPE_IEG
       PARAMETER (CDI_FILETYPE_IEG       =  9)
-      INTEGER    FILETYPE_GRB          
+      INTEGER    FILETYPE_GRB
       PARAMETER (FILETYPE_GRB           =  1)
-      INTEGER    FILETYPE_GRB2         
+      INTEGER    FILETYPE_GRB2
       PARAMETER (FILETYPE_GRB2          =  2)
-      INTEGER    FILETYPE_NC           
+      INTEGER    FILETYPE_NC
       PARAMETER (FILETYPE_NC            =  3)
-      INTEGER    FILETYPE_NC2          
+      INTEGER    FILETYPE_NC2
       PARAMETER (FILETYPE_NC2           =  4)
-      INTEGER    FILETYPE_NC4          
+      INTEGER    FILETYPE_NC4
       PARAMETER (FILETYPE_NC4           =  5)
-      INTEGER    FILETYPE_NC4C         
+      INTEGER    FILETYPE_NC4C
       PARAMETER (FILETYPE_NC4C          =  6)
-      INTEGER    FILETYPE_SRV          
+      INTEGER    FILETYPE_SRV
       PARAMETER (FILETYPE_SRV           =  7)
-      INTEGER    FILETYPE_EXT          
+      INTEGER    FILETYPE_EXT
       PARAMETER (FILETYPE_EXT           =  8)
-      INTEGER    FILETYPE_IEG          
+      INTEGER    FILETYPE_IEG
       PARAMETER (FILETYPE_IEG           =  9)
 !
 !  Compress types
 !
-      INTEGER    CDI_COMPRESS_NONE     
+      INTEGER    CDI_COMPRESS_NONE
       PARAMETER (CDI_COMPRESS_NONE      =  0)
-      INTEGER    CDI_COMPRESS_SZIP     
+      INTEGER    CDI_COMPRESS_SZIP
       PARAMETER (CDI_COMPRESS_SZIP      =  1)
-      INTEGER    CDI_COMPRESS_GZIP     
+      INTEGER    CDI_COMPRESS_GZIP
       PARAMETER (CDI_COMPRESS_GZIP      =  2)
-      INTEGER    CDI_COMPRESS_BZIP2    
+      INTEGER    CDI_COMPRESS_BZIP2
       PARAMETER (CDI_COMPRESS_BZIP2     =  3)
-      INTEGER    CDI_COMPRESS_ZIP      
+      INTEGER    CDI_COMPRESS_ZIP
       PARAMETER (CDI_COMPRESS_ZIP       =  4)
-      INTEGER    CDI_COMPRESS_JPEG     
+      INTEGER    CDI_COMPRESS_JPEG
       PARAMETER (CDI_COMPRESS_JPEG      =  5)
 !
 !  external data types
 !
-      INTEGER    CDI_DATATYPE_PACK     
+      INTEGER    CDI_DATATYPE_PACK
       PARAMETER (CDI_DATATYPE_PACK      =  0)
-      INTEGER    CDI_DATATYPE_PACK1    
+      INTEGER    CDI_DATATYPE_PACK1
       PARAMETER (CDI_DATATYPE_PACK1     =  1)
-      INTEGER    CDI_DATATYPE_PACK2    
+      INTEGER    CDI_DATATYPE_PACK2
       PARAMETER (CDI_DATATYPE_PACK2     =  2)
-      INTEGER    CDI_DATATYPE_PACK3    
+      INTEGER    CDI_DATATYPE_PACK3
       PARAMETER (CDI_DATATYPE_PACK3     =  3)
-      INTEGER    CDI_DATATYPE_PACK4    
+      INTEGER    CDI_DATATYPE_PACK4
       PARAMETER (CDI_DATATYPE_PACK4     =  4)
-      INTEGER    CDI_DATATYPE_PACK5    
+      INTEGER    CDI_DATATYPE_PACK5
       PARAMETER (CDI_DATATYPE_PACK5     =  5)
-      INTEGER    CDI_DATATYPE_PACK6    
+      INTEGER    CDI_DATATYPE_PACK6
       PARAMETER (CDI_DATATYPE_PACK6     =  6)
-      INTEGER    CDI_DATATYPE_PACK7    
+      INTEGER    CDI_DATATYPE_PACK7
       PARAMETER (CDI_DATATYPE_PACK7     =  7)
-      INTEGER    CDI_DATATYPE_PACK8    
+      INTEGER    CDI_DATATYPE_PACK8
       PARAMETER (CDI_DATATYPE_PACK8     =  8)
-      INTEGER    CDI_DATATYPE_PACK9    
+      INTEGER    CDI_DATATYPE_PACK9
       PARAMETER (CDI_DATATYPE_PACK9     =  9)
-      INTEGER    CDI_DATATYPE_PACK10   
+      INTEGER    CDI_DATATYPE_PACK10
       PARAMETER (CDI_DATATYPE_PACK10    = 10)
-      INTEGER    CDI_DATATYPE_PACK11   
+      INTEGER    CDI_DATATYPE_PACK11
       PARAMETER (CDI_DATATYPE_PACK11    = 11)
-      INTEGER    CDI_DATATYPE_PACK12   
+      INTEGER    CDI_DATATYPE_PACK12
       PARAMETER (CDI_DATATYPE_PACK12    = 12)
-      INTEGER    CDI_DATATYPE_PACK13   
+      INTEGER    CDI_DATATYPE_PACK13
       PARAMETER (CDI_DATATYPE_PACK13    = 13)
-      INTEGER    CDI_DATATYPE_PACK14   
+      INTEGER    CDI_DATATYPE_PACK14
       PARAMETER (CDI_DATATYPE_PACK14    = 14)
-      INTEGER    CDI_DATATYPE_PACK15   
+      INTEGER    CDI_DATATYPE_PACK15
       PARAMETER (CDI_DATATYPE_PACK15    = 15)
-      INTEGER    CDI_DATATYPE_PACK16   
+      INTEGER    CDI_DATATYPE_PACK16
       PARAMETER (CDI_DATATYPE_PACK16    = 16)
-      INTEGER    CDI_DATATYPE_PACK17   
+      INTEGER    CDI_DATATYPE_PACK17
       PARAMETER (CDI_DATATYPE_PACK17    = 17)
-      INTEGER    CDI_DATATYPE_PACK18   
+      INTEGER    CDI_DATATYPE_PACK18
       PARAMETER (CDI_DATATYPE_PACK18    = 18)
-      INTEGER    CDI_DATATYPE_PACK19   
+      INTEGER    CDI_DATATYPE_PACK19
       PARAMETER (CDI_DATATYPE_PACK19    = 19)
-      INTEGER    CDI_DATATYPE_PACK20   
+      INTEGER    CDI_DATATYPE_PACK20
       PARAMETER (CDI_DATATYPE_PACK20    = 20)
-      INTEGER    CDI_DATATYPE_PACK21   
+      INTEGER    CDI_DATATYPE_PACK21
       PARAMETER (CDI_DATATYPE_PACK21    = 21)
-      INTEGER    CDI_DATATYPE_PACK22   
+      INTEGER    CDI_DATATYPE_PACK22
       PARAMETER (CDI_DATATYPE_PACK22    = 22)
-      INTEGER    CDI_DATATYPE_PACK23   
+      INTEGER    CDI_DATATYPE_PACK23
       PARAMETER (CDI_DATATYPE_PACK23    = 23)
-      INTEGER    CDI_DATATYPE_PACK24   
+      INTEGER    CDI_DATATYPE_PACK24
       PARAMETER (CDI_DATATYPE_PACK24    = 24)
-      INTEGER    CDI_DATATYPE_PACK25   
+      INTEGER    CDI_DATATYPE_PACK25
       PARAMETER (CDI_DATATYPE_PACK25    = 25)
-      INTEGER    CDI_DATATYPE_PACK26   
+      INTEGER    CDI_DATATYPE_PACK26
       PARAMETER (CDI_DATATYPE_PACK26    = 26)
-      INTEGER    CDI_DATATYPE_PACK27   
+      INTEGER    CDI_DATATYPE_PACK27
       PARAMETER (CDI_DATATYPE_PACK27    = 27)
-      INTEGER    CDI_DATATYPE_PACK28   
+      INTEGER    CDI_DATATYPE_PACK28
       PARAMETER (CDI_DATATYPE_PACK28    = 28)
-      INTEGER    CDI_DATATYPE_PACK29   
+      INTEGER    CDI_DATATYPE_PACK29
       PARAMETER (CDI_DATATYPE_PACK29    = 29)
-      INTEGER    CDI_DATATYPE_PACK30   
+      INTEGER    CDI_DATATYPE_PACK30
       PARAMETER (CDI_DATATYPE_PACK30    = 30)
-      INTEGER    CDI_DATATYPE_PACK31   
+      INTEGER    CDI_DATATYPE_PACK31
       PARAMETER (CDI_DATATYPE_PACK31    = 31)
-      INTEGER    CDI_DATATYPE_PACK32   
+      INTEGER    CDI_DATATYPE_PACK32
       PARAMETER (CDI_DATATYPE_PACK32    = 32)
-      INTEGER    CDI_DATATYPE_CPX32    
+      INTEGER    CDI_DATATYPE_CPX32
       PARAMETER (CDI_DATATYPE_CPX32     = 64)
-      INTEGER    CDI_DATATYPE_CPX64    
+      INTEGER    CDI_DATATYPE_CPX64
       PARAMETER (CDI_DATATYPE_CPX64     = 128)
-      INTEGER    CDI_DATATYPE_FLT32    
+      INTEGER    CDI_DATATYPE_FLT32
       PARAMETER (CDI_DATATYPE_FLT32     = 132)
-      INTEGER    CDI_DATATYPE_FLT64    
+      INTEGER    CDI_DATATYPE_FLT64
       PARAMETER (CDI_DATATYPE_FLT64     = 164)
-      INTEGER    CDI_DATATYPE_INT8     
+      INTEGER    CDI_DATATYPE_INT8
       PARAMETER (CDI_DATATYPE_INT8      = 208)
-      INTEGER    CDI_DATATYPE_INT16    
+      INTEGER    CDI_DATATYPE_INT16
       PARAMETER (CDI_DATATYPE_INT16     = 216)
-      INTEGER    CDI_DATATYPE_INT32    
+      INTEGER    CDI_DATATYPE_INT32
       PARAMETER (CDI_DATATYPE_INT32     = 232)
-      INTEGER    CDI_DATATYPE_UINT8    
+      INTEGER    CDI_DATATYPE_UINT8
       PARAMETER (CDI_DATATYPE_UINT8     = 308)
-      INTEGER    CDI_DATATYPE_UINT16   
+      INTEGER    CDI_DATATYPE_UINT16
       PARAMETER (CDI_DATATYPE_UINT16    = 316)
-      INTEGER    CDI_DATATYPE_UINT32   
+      INTEGER    CDI_DATATYPE_UINT32
       PARAMETER (CDI_DATATYPE_UINT32    = 332)
-      INTEGER    DATATYPE_PACK         
+      INTEGER    DATATYPE_PACK
       PARAMETER (DATATYPE_PACK          =  0)
-      INTEGER    DATATYPE_PACK8        
+      INTEGER    DATATYPE_PACK8
       PARAMETER (DATATYPE_PACK8         =  8)
-      INTEGER    DATATYPE_PACK16       
+      INTEGER    DATATYPE_PACK16
       PARAMETER (DATATYPE_PACK16        = 16)
-      INTEGER    DATATYPE_PACK24       
+      INTEGER    DATATYPE_PACK24
       PARAMETER (DATATYPE_PACK24        = 24)
-      INTEGER    DATATYPE_FLT32        
+      INTEGER    DATATYPE_FLT32
       PARAMETER (DATATYPE_FLT32         = 132)
-      INTEGER    DATATYPE_FLT64        
+      INTEGER    DATATYPE_FLT64
       PARAMETER (DATATYPE_FLT64         = 164)
-      INTEGER    DATATYPE_INT32        
+      INTEGER    DATATYPE_INT32
       PARAMETER (DATATYPE_INT32         = 232)
 !
 !  internal data types
 !
-      INTEGER    CDI_DATATYPE_INT      
+      INTEGER    CDI_DATATYPE_INT
       PARAMETER (CDI_DATATYPE_INT       = 251)
-      INTEGER    CDI_DATATYPE_FLT      
+      INTEGER    CDI_DATATYPE_FLT
       PARAMETER (CDI_DATATYPE_FLT       = 252)
-      INTEGER    CDI_DATATYPE_TXT      
+      INTEGER    CDI_DATATYPE_TXT
       PARAMETER (CDI_DATATYPE_TXT       = 253)
-      INTEGER    CDI_DATATYPE_CPX      
+      INTEGER    CDI_DATATYPE_CPX
       PARAMETER (CDI_DATATYPE_CPX       = 254)
-      INTEGER    CDI_DATATYPE_UCHAR    
+      INTEGER    CDI_DATATYPE_UCHAR
       PARAMETER (CDI_DATATYPE_UCHAR     = 255)
-      INTEGER    CDI_DATATYPE_LONG     
+      INTEGER    CDI_DATATYPE_LONG
       PARAMETER (CDI_DATATYPE_LONG      = 256)
-      INTEGER    DATATYPE_INT          
+      INTEGER    DATATYPE_INT
       PARAMETER (DATATYPE_INT           = 251)
-      INTEGER    DATATYPE_FLT          
+      INTEGER    DATATYPE_FLT
       PARAMETER (DATATYPE_FLT           = 252)
-      INTEGER    DATATYPE_TXT          
+      INTEGER    DATATYPE_TXT
       PARAMETER (DATATYPE_TXT           = 253)
-      INTEGER    DATATYPE_CPX          
+      INTEGER    DATATYPE_CPX
       PARAMETER (DATATYPE_CPX           = 254)
-      INTEGER    DATATYPE_UCHAR        
+      INTEGER    DATATYPE_UCHAR
       PARAMETER (DATATYPE_UCHAR         = 255)
-      INTEGER    DATATYPE_LONG         
+      INTEGER    DATATYPE_LONG
       PARAMETER (DATATYPE_LONG          = 256)
 !
 !  Chunks
 !
-      INTEGER    CDI_CHUNK_AUTO        
+      INTEGER    CDI_CHUNK_AUTO
       PARAMETER (CDI_CHUNK_AUTO         =  1)
-      INTEGER    CDI_CHUNK_GRID        
+      INTEGER    CDI_CHUNK_GRID
       PARAMETER (CDI_CHUNK_GRID         =  2)
-      INTEGER    CDI_CHUNK_LINES       
+      INTEGER    CDI_CHUNK_LINES
       PARAMETER (CDI_CHUNK_LINES        =  3)
 !
 !  GRID types
 !
-      INTEGER    GRID_GENERIC          
+      INTEGER    GRID_GENERIC
       PARAMETER (GRID_GENERIC           =  1)
-      INTEGER    GRID_GAUSSIAN         
+      INTEGER    GRID_GAUSSIAN
       PARAMETER (GRID_GAUSSIAN          =  2)
-      INTEGER    GRID_GAUSSIAN_REDUCED 
+      INTEGER    GRID_GAUSSIAN_REDUCED
       PARAMETER (GRID_GAUSSIAN_REDUCED  =  3)
-      INTEGER    GRID_LONLAT           
+      INTEGER    GRID_LONLAT
       PARAMETER (GRID_LONLAT            =  4)
-      INTEGER    GRID_SPECTRAL         
+      INTEGER    GRID_SPECTRAL
       PARAMETER (GRID_SPECTRAL          =  5)
-      INTEGER    GRID_FOURIER          
+      INTEGER    GRID_FOURIER
       PARAMETER (GRID_FOURIER           =  6)
-      INTEGER    GRID_GME              
+      INTEGER    GRID_GME
       PARAMETER (GRID_GME               =  7)
-      INTEGER    GRID_TRAJECTORY       
+      INTEGER    GRID_TRAJECTORY
       PARAMETER (GRID_TRAJECTORY        =  8)
-      INTEGER    GRID_UNSTRUCTURED     
+      INTEGER    GRID_UNSTRUCTURED
       PARAMETER (GRID_UNSTRUCTURED      =  9)
-      INTEGER    GRID_CURVILINEAR      
+      INTEGER    GRID_CURVILINEAR
       PARAMETER (GRID_CURVILINEAR       = 10)
-      INTEGER    GRID_LCC              
+      INTEGER    GRID_LCC
       PARAMETER (GRID_LCC               = 11)
-      INTEGER    GRID_PROJECTION       
+      INTEGER    GRID_PROJECTION
       PARAMETER (GRID_PROJECTION        = 12)
-      INTEGER    CDI_PROJ_RLL          
+      INTEGER    CDI_PROJ_RLL
       PARAMETER (CDI_PROJ_RLL           = 21)
-      INTEGER    CDI_PROJ_LCC          
+      INTEGER    CDI_PROJ_LCC
       PARAMETER (CDI_PROJ_LCC           = 22)
-      INTEGER    CDI_PROJ_LAEA         
+      INTEGER    CDI_PROJ_LAEA
       PARAMETER (CDI_PROJ_LAEA          = 23)
-      INTEGER    CDI_PROJ_SINU         
+      INTEGER    CDI_PROJ_SINU
       PARAMETER (CDI_PROJ_SINU          = 24)
 !
 !  ZAXIS types
 !
-      INTEGER    ZAXIS_SURFACE         
+      INTEGER    ZAXIS_SURFACE
       PARAMETER (ZAXIS_SURFACE          =  0)
-      INTEGER    ZAXIS_GENERIC         
+      INTEGER    ZAXIS_GENERIC
       PARAMETER (ZAXIS_GENERIC          =  1)
-      INTEGER    ZAXIS_HYBRID          
+      INTEGER    ZAXIS_HYBRID
       PARAMETER (ZAXIS_HYBRID           =  2)
-      INTEGER    ZAXIS_HYBRID_HALF     
+      INTEGER    ZAXIS_HYBRID_HALF
       PARAMETER (ZAXIS_HYBRID_HALF      =  3)
-      INTEGER    ZAXIS_PRESSURE        
+      INTEGER    ZAXIS_PRESSURE
       PARAMETER (ZAXIS_PRESSURE         =  4)
-      INTEGER    ZAXIS_HEIGHT          
+      INTEGER    ZAXIS_HEIGHT
       PARAMETER (ZAXIS_HEIGHT           =  5)
-      INTEGER    ZAXIS_DEPTH_BELOW_SEA 
+      INTEGER    ZAXIS_DEPTH_BELOW_SEA
       PARAMETER (ZAXIS_DEPTH_BELOW_SEA  =  6)
       INTEGER    ZAXIS_DEPTH_BELOW_LAND
       PARAMETER (ZAXIS_DEPTH_BELOW_LAND =  7)
-      INTEGER    ZAXIS_ISENTROPIC      
+      INTEGER    ZAXIS_ISENTROPIC
       PARAMETER (ZAXIS_ISENTROPIC       =  8)
-      INTEGER    ZAXIS_TRAJECTORY      
+      INTEGER    ZAXIS_TRAJECTORY
       PARAMETER (ZAXIS_TRAJECTORY       =  9)
-      INTEGER    ZAXIS_ALTITUDE        
+      INTEGER    ZAXIS_ALTITUDE
       PARAMETER (ZAXIS_ALTITUDE         = 10)
-      INTEGER    ZAXIS_SIGMA           
+      INTEGER    ZAXIS_SIGMA
       PARAMETER (ZAXIS_SIGMA            = 11)
-      INTEGER    ZAXIS_MEANSEA         
+      INTEGER    ZAXIS_MEANSEA
       PARAMETER (ZAXIS_MEANSEA          = 12)
-      INTEGER    ZAXIS_TOA             
+      INTEGER    ZAXIS_TOA
       PARAMETER (ZAXIS_TOA              = 13)
-      INTEGER    ZAXIS_SEA_BOTTOM      
+      INTEGER    ZAXIS_SEA_BOTTOM
       PARAMETER (ZAXIS_SEA_BOTTOM       = 14)
-      INTEGER    ZAXIS_ATMOSPHERE      
+      INTEGER    ZAXIS_ATMOSPHERE
       PARAMETER (ZAXIS_ATMOSPHERE       = 15)
-      INTEGER    ZAXIS_CLOUD_BASE      
+      INTEGER    ZAXIS_CLOUD_BASE
       PARAMETER (ZAXIS_CLOUD_BASE       = 16)
-      INTEGER    ZAXIS_CLOUD_TOP       
+      INTEGER    ZAXIS_CLOUD_TOP
       PARAMETER (ZAXIS_CLOUD_TOP        = 17)
-      INTEGER    ZAXIS_ISOTHERM_ZERO   
+      INTEGER    ZAXIS_ISOTHERM_ZERO
       PARAMETER (ZAXIS_ISOTHERM_ZERO    = 18)
-      INTEGER    ZAXIS_SNOW            
+      INTEGER    ZAXIS_SNOW
       PARAMETER (ZAXIS_SNOW             = 19)
-      INTEGER    ZAXIS_LAKE_BOTTOM     
+      INTEGER    ZAXIS_LAKE_BOTTOM
       PARAMETER (ZAXIS_LAKE_BOTTOM      = 20)
-      INTEGER    ZAXIS_SEDIMENT_BOTTOM 
+      INTEGER    ZAXIS_SEDIMENT_BOTTOM
       PARAMETER (ZAXIS_SEDIMENT_BOTTOM  = 21)
       INTEGER    ZAXIS_SEDIMENT_BOTTOM_TA
       PARAMETER (ZAXIS_SEDIMENT_BOTTOM_TA = 22)
       INTEGER    ZAXIS_SEDIMENT_BOTTOM_TW
       PARAMETER (ZAXIS_SEDIMENT_BOTTOM_TW = 23)
-      INTEGER    ZAXIS_MIX_LAYER       
+      INTEGER    ZAXIS_MIX_LAYER
       PARAMETER (ZAXIS_MIX_LAYER        = 24)
-      INTEGER    ZAXIS_REFERENCE       
+      INTEGER    ZAXIS_REFERENCE
       PARAMETER (ZAXIS_REFERENCE        = 25)
 !
 !  SUBTYPE types
 !
-      INTEGER    MAX_KV_PAIRS_MATCH    
+      INTEGER    MAX_KV_PAIRS_MATCH
       PARAMETER (MAX_KV_PAIRS_MATCH     = 10)
 !
 !  Data structure defining a key-value search, possibly with multiple
@@ -346,94 +346,94 @@
 !
 !  TIME types
 !
-      INTEGER    TIME_CONSTANT         
+      INTEGER    TIME_CONSTANT
       PARAMETER (TIME_CONSTANT          =  0)
-      INTEGER    TIME_VARIABLE         
+      INTEGER    TIME_VARIABLE
       PARAMETER (TIME_VARIABLE          =  1)
 !
 !  TSTEP types
 !
-      INTEGER    TSTEP_CONSTANT        
+      INTEGER    TSTEP_CONSTANT
       PARAMETER (TSTEP_CONSTANT         =  0)
-      INTEGER    TSTEP_INSTANT         
+      INTEGER    TSTEP_INSTANT
       PARAMETER (TSTEP_INSTANT          =  1)
-      INTEGER    TSTEP_AVG             
+      INTEGER    TSTEP_AVG
       PARAMETER (TSTEP_AVG              =  2)
-      INTEGER    TSTEP_ACCUM           
+      INTEGER    TSTEP_ACCUM
       PARAMETER (TSTEP_ACCUM            =  3)
-      INTEGER    TSTEP_MAX             
+      INTEGER    TSTEP_MAX
       PARAMETER (TSTEP_MAX              =  4)
-      INTEGER    TSTEP_MIN             
+      INTEGER    TSTEP_MIN
       PARAMETER (TSTEP_MIN              =  5)
-      INTEGER    TSTEP_DIFF            
+      INTEGER    TSTEP_DIFF
       PARAMETER (TSTEP_DIFF             =  6)
-      INTEGER    TSTEP_RMS             
+      INTEGER    TSTEP_RMS
       PARAMETER (TSTEP_RMS              =  7)
-      INTEGER    TSTEP_SD              
+      INTEGER    TSTEP_SD
       PARAMETER (TSTEP_SD               =  8)
-      INTEGER    TSTEP_COV             
+      INTEGER    TSTEP_COV
       PARAMETER (TSTEP_COV              =  9)
-      INTEGER    TSTEP_RATIO           
+      INTEGER    TSTEP_RATIO
       PARAMETER (TSTEP_RATIO            = 10)
-      INTEGER    TSTEP_RANGE           
+      INTEGER    TSTEP_RANGE
       PARAMETER (TSTEP_RANGE            = 11)
-      INTEGER    TSTEP_INSTANT2        
+      INTEGER    TSTEP_INSTANT2
       PARAMETER (TSTEP_INSTANT2         = 12)
-      INTEGER    TSTEP_INSTANT3        
+      INTEGER    TSTEP_INSTANT3
       PARAMETER (TSTEP_INSTANT3         = 13)
 !
 !  TAXIS types
 !
-      INTEGER    TAXIS_ABSOLUTE        
+      INTEGER    TAXIS_ABSOLUTE
       PARAMETER (TAXIS_ABSOLUTE         =  1)
-      INTEGER    TAXIS_RELATIVE        
+      INTEGER    TAXIS_RELATIVE
       PARAMETER (TAXIS_RELATIVE         =  2)
-      INTEGER    TAXIS_FORECAST        
+      INTEGER    TAXIS_FORECAST
       PARAMETER (TAXIS_FORECAST         =  3)
 !
 !  TUNIT types
 !
-      INTEGER    TUNIT_SECOND          
+      INTEGER    TUNIT_SECOND
       PARAMETER (TUNIT_SECOND           =  1)
-      INTEGER    TUNIT_MINUTE          
+      INTEGER    TUNIT_MINUTE
       PARAMETER (TUNIT_MINUTE           =  2)
-      INTEGER    TUNIT_QUARTER         
+      INTEGER    TUNIT_QUARTER
       PARAMETER (TUNIT_QUARTER          =  3)
-      INTEGER    TUNIT_30MINUTES       
+      INTEGER    TUNIT_30MINUTES
       PARAMETER (TUNIT_30MINUTES        =  4)
-      INTEGER    TUNIT_HOUR            
+      INTEGER    TUNIT_HOUR
       PARAMETER (TUNIT_HOUR             =  5)
-      INTEGER    TUNIT_3HOURS          
+      INTEGER    TUNIT_3HOURS
       PARAMETER (TUNIT_3HOURS           =  6)
-      INTEGER    TUNIT_6HOURS          
+      INTEGER    TUNIT_6HOURS
       PARAMETER (TUNIT_6HOURS           =  7)
-      INTEGER    TUNIT_12HOURS         
+      INTEGER    TUNIT_12HOURS
       PARAMETER (TUNIT_12HOURS          =  8)
-      INTEGER    TUNIT_DAY             
+      INTEGER    TUNIT_DAY
       PARAMETER (TUNIT_DAY              =  9)
-      INTEGER    TUNIT_MONTH           
+      INTEGER    TUNIT_MONTH
       PARAMETER (TUNIT_MONTH            = 10)
-      INTEGER    TUNIT_YEAR            
+      INTEGER    TUNIT_YEAR
       PARAMETER (TUNIT_YEAR             = 11)
 !
 !  CALENDAR types
 !
-      INTEGER    CALENDAR_STANDARD     
+      INTEGER    CALENDAR_STANDARD
       PARAMETER (CALENDAR_STANDARD      =  0)
-      INTEGER    CALENDAR_PROLEPTIC    
+      INTEGER    CALENDAR_PROLEPTIC
       PARAMETER (CALENDAR_PROLEPTIC     =  1)
-      INTEGER    CALENDAR_360DAYS      
+      INTEGER    CALENDAR_360DAYS
       PARAMETER (CALENDAR_360DAYS       =  2)
-      INTEGER    CALENDAR_365DAYS      
+      INTEGER    CALENDAR_365DAYS
       PARAMETER (CALENDAR_365DAYS       =  3)
-      INTEGER    CALENDAR_366DAYS      
+      INTEGER    CALENDAR_366DAYS
       PARAMETER (CALENDAR_366DAYS       =  4)
-      INTEGER    CALENDAR_NONE         
+      INTEGER    CALENDAR_NONE
       PARAMETER (CALENDAR_NONE          =  5)
 !
 !  number of unsigned char needed to store UUID
 !
-      INTEGER    CDI_UUID_SIZE         
+      INTEGER    CDI_UUID_SIZE
       PARAMETER (CDI_UUID_SIZE          = 16)
 !
 !  Structs that are used to return data to the user
@@ -709,7 +709,7 @@
 !                     streamWriteVarChunk
 !                                    (INTEGER         streamID,
 !                                     INTEGER         varID,
-!                                     INTEGER         rect(*),
+!                                     INTEGER         rect(2,3),
 !                                     DOUBLEPRECISION data(*),
 !                                     INTEGER         nmiss)
       EXTERNAL        streamWriteVarChunk
@@ -1589,44 +1589,44 @@
 !
 !  CDI grid string key values
 !
-      INTEGER    CDI_KEY_XNAME         
+      INTEGER    CDI_KEY_XNAME
       PARAMETER (CDI_KEY_XNAME          = 901)
-      INTEGER    CDI_KEY_XDIMNAME      
+      INTEGER    CDI_KEY_XDIMNAME
       PARAMETER (CDI_KEY_XDIMNAME       = 902)
-      INTEGER    CDI_KEY_XLONGNAME     
+      INTEGER    CDI_KEY_XLONGNAME
       PARAMETER (CDI_KEY_XLONGNAME      = 903)
-      INTEGER    CDI_KEY_XUNITS        
+      INTEGER    CDI_KEY_XUNITS
       PARAMETER (CDI_KEY_XUNITS         = 904)
-      INTEGER    CDI_KEY_YNAME         
+      INTEGER    CDI_KEY_YNAME
       PARAMETER (CDI_KEY_YNAME          = 911)
-      INTEGER    CDI_KEY_YDIMNAME      
+      INTEGER    CDI_KEY_YDIMNAME
       PARAMETER (CDI_KEY_YDIMNAME       = 912)
-      INTEGER    CDI_KEY_YLONGNAME     
+      INTEGER    CDI_KEY_YLONGNAME
       PARAMETER (CDI_KEY_YLONGNAME      = 913)
-      INTEGER    CDI_KEY_YUNITS        
+      INTEGER    CDI_KEY_YUNITS
       PARAMETER (CDI_KEY_YUNITS         = 914)
-      INTEGER    CDI_KEY_VDIMNAME      
+      INTEGER    CDI_KEY_VDIMNAME
       PARAMETER (CDI_KEY_VDIMNAME       = 920)
-      INTEGER    CDI_KEY_MAPPING       
+      INTEGER    CDI_KEY_MAPPING
       PARAMETER (CDI_KEY_MAPPING        = 921)
-      INTEGER    CDI_KEY_MAPNAME       
+      INTEGER    CDI_KEY_MAPNAME
       PARAMETER (CDI_KEY_MAPNAME        = 922)
 !
 !  CDI zaxis string key values
 !
-      INTEGER    CDI_KEY_NAME          
+      INTEGER    CDI_KEY_NAME
       PARAMETER (CDI_KEY_NAME           = 941)
-      INTEGER    CDI_KEY_DIMNAME       
+      INTEGER    CDI_KEY_DIMNAME
       PARAMETER (CDI_KEY_DIMNAME        = 942)
-      INTEGER    CDI_KEY_LONGNAME      
+      INTEGER    CDI_KEY_LONGNAME
       PARAMETER (CDI_KEY_LONGNAME       = 943)
-      INTEGER    CDI_KEY_UNITS         
+      INTEGER    CDI_KEY_UNITS
       PARAMETER (CDI_KEY_UNITS          = 944)
-      INTEGER    CDI_KEY_PSNAME        
+      INTEGER    CDI_KEY_PSNAME
       PARAMETER (CDI_KEY_PSNAME         = 950)
-      INTEGER    CDI_KEY_P0NAME        
+      INTEGER    CDI_KEY_P0NAME
       PARAMETER (CDI_KEY_P0NAME         = 951)
-      INTEGER    CDI_KEY_P0VALUE       
+      INTEGER    CDI_KEY_P0VALUE
       PARAMETER (CDI_KEY_P0VALUE        = 952)
       INTEGER         cdiGridDefKeyStr
 !                                    (INTEGER         gridID,
@@ -1846,28 +1846,32 @@
 !
 !                     gridDefParamLCC
 !                                    (INTEGER         gridID,
-!                                     DOUBLEPRECISION originLon,
-!                                     DOUBLEPRECISION originLat,
-!                                     DOUBLEPRECISION lonParY,
-!                                     DOUBLEPRECISION lat1,
-!                                     DOUBLEPRECISION lat2,
-!                                     DOUBLEPRECISION xinc,
-!                                     DOUBLEPRECISION yinc,
-!                                     INTEGER         projflag,
-!                                     INTEGER         scanflag)
+!                                     DOUBLEPRECISION missval,
+!                                     DOUBLEPRECISION lon_0,
+!                                     DOUBLEPRECISION lat_0,
+!                                     DOUBLEPRECISION lat_1,
+!                                     DOUBLEPRECISION lat_2,
+!                                     DOUBLEPRECISION a,
+!                                     DOUBLEPRECISION rf,
+!                                     DOUBLEPRECISION xval_0,
+!                                     DOUBLEPRECISION yval_0,
+!                                     DOUBLEPRECISION x_0,
+!                                     DOUBLEPRECISION y_0)
       EXTERNAL        gridDefParamLCC
 
-!                     gridInqParamLCC
+      INTEGER         gridInqParamLCC
 !                                    (INTEGER         gridID,
-!                                     DOUBLEPRECISION originLon,
-!                                     DOUBLEPRECISION originLat,
-!                                     DOUBLEPRECISION lonParY,
-!                                     DOUBLEPRECISION lat1,
-!                                     DOUBLEPRECISION lat2,
-!                                     DOUBLEPRECISION xinc,
-!                                     DOUBLEPRECISION yinc,
-!                                     INTEGER         projflag,
-!                                     INTEGER         scanflag)
+!                                     DOUBLEPRECISION missval,
+!                                     DOUBLEPRECISION lon_0,
+!                                     DOUBLEPRECISION lat_0,
+!                                     DOUBLEPRECISION lat_1,
+!                                     DOUBLEPRECISION lat_2,
+!                                     DOUBLEPRECISION a,
+!                                     DOUBLEPRECISION rf,
+!                                     DOUBLEPRECISION xval_0,
+!                                     DOUBLEPRECISION yval_0,
+!                                     DOUBLEPRECISION x_0,
+!                                     DOUBLEPRECISION y_0)
       EXTERNAL        gridInqParamLCC
 
 !                     gridDefArea
@@ -1938,6 +1942,24 @@
 !                                    (INTEGER         gridID)
       EXTERNAL        gridInqComplexPacking
 
+!                     gridDefUvRelativeToGrid
+!                                    (INTEGER         gridID,
+!                                     INTEGER         uvRelativeToGrid)
+      EXTERNAL        gridDefUvRelativeToGrid
+
+      INTEGER         gridInqUvRelativeToGrid
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqUvRelativeToGrid
+
+!                     gridDefScanningMode
+!                                    (INTEGER         gridID,
+!                                     INTEGER         mode)
+      EXTERNAL        gridDefScanningMode
+
+      INTEGER         gridInqScanningMode
+!                                    (INTEGER         gridID)
+      EXTERNAL        gridInqScanningMode
+
 !
 !  ZAXIS routines
 !
diff --git a/libcdi/src/cdiFortran.c b/libcdi/src/cdiFortran.c
index 2202400..de7943e 100644
--- a/libcdi/src/cdiFortran.c
+++ b/libcdi/src/cdiFortran.c
@@ -11,7 +11,19 @@
 #if defined (HAVE_CF_INTERFACE)
 
 #if ! defined (__CFORTRAN_LOADED)
+#  if defined __clang__
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wreserved-id-macro"
+#  endif
 #  include "cfortran.h"
+#  if defined __clang__
+#    pragma GCC diagnostic pop
+#  endif
+#endif
+/* These functions are meant to be called from Fortran and don't
+ * need an interface declaration in a C header. */
+#if defined __clang__
+#  pragma GCC diagnostic ignored "-Wmissing-prototypes"
 #endif
 
 
@@ -385,8 +397,8 @@ FCALLSCSUB5 (gridInqParamGME, GRIDINQPARAMGME, gridinqparamgme, INT, PINT, PINT,
 
 /*  Lambert Conformal Conic grid (GRIB version)  */
 
-FCALLSCSUB10 (gridDefParamLCC, GRIDDEFPARAMLCC, griddefparamlcc, INT, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, INT, INT)
-FCALLSCSUB10 (gridInqParamLCC, GRIDINQPARAMLCC, gridinqparamlcc, INT, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PINT, PINT)
+FCALLSCSUB12 (gridDefParamLCC, GRIDDEFPARAMLCC, griddefparamlcc, INT, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE)
+FCALLSCFUN12 (INT, gridInqParamLCC, GRIDINQPARAMLCC, gridinqparamlcc, INT, DOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE, PDOUBLE)
 FCALLSCSUB2 (gridDefArea, GRIDDEFAREA, griddefarea, INT, DOUBLEV)
 FCALLSCSUB2 (gridInqArea, GRIDINQAREA, gridinqarea, INT, DOUBLEV)
 FCALLSCFUN1 (INT, gridHasArea, GRIDHASAREA, gridhasarea, INT)
@@ -401,6 +413,10 @@ FCALLSCSUB2 (gridInqRowlon, GRIDINQROWLON, gridinqrowlon, INT, INTV)
 FCALLSCSUB2 (gridChangeType, GRIDCHANGETYPE, gridchangetype, INT, INT)
 FCALLSCSUB2 (gridDefComplexPacking, GRIDDEFCOMPLEXPACKING, griddefcomplexpacking, INT, INT)
 FCALLSCFUN1 (INT, gridInqComplexPacking, GRIDINQCOMPLEXPACKING, gridinqcomplexpacking, INT)
+FCALLSCSUB2 (gridDefUvRelativeToGrid, GRIDDEFUVRELATIVETOGRID, griddefuvrelativetogrid, INT, INT)
+FCALLSCFUN1 (INT, gridInqUvRelativeToGrid, GRIDINQUVRELATIVETOGRID, gridinquvrelativetogrid, INT)
+FCALLSCSUB2 (gridDefScanningMode, GRIDDEFSCANNINGMODE, griddefscanningmode, INT, INT)
+FCALLSCFUN1 (INT, gridInqScanningMode, GRIDINQSCANNINGMODE, gridinqscanningmode, INT)
 
 /*  ZAXIS routines  */
 
@@ -564,4 +580,7 @@ FCALLSCFUN4 (INT, subtypeInqAttribute, SUBTYPEINQATTRIBUTE, subtypeinqattribute,
 FCALLSCFUN2 (INT, vlistInqVarSubtype, VLISTINQVARSUBTYPE, vlistinqvarsubtype, INT, INT)
 FCALLSCSUB3 (gribapiLibraryVersion, GRIBAPILIBRARYVERSION, gribapilibraryversion, PINT, PINT, PINT)
 
+#if defined __clang__
+#  pragma GCC diagnostic pop
+#endif
 #endif
diff --git a/libcdi/src/cdi_int.c b/libcdi/src/cdi_int.c
index 0894198..db3b092 100644
--- a/libcdi/src/cdi_int.c
+++ b/libcdi/src/cdi_int.c
@@ -5,6 +5,7 @@
 #include <stdarg.h>
 #include <ctype.h>
 
+#include "binary.h"
 #include "cdf.h"
 #include "cdi.h"
 #include "cdi_int.h"
@@ -148,6 +149,48 @@ void cdiPrintVersion(void)
   fprintf(stderr, "    FILE library version : %s\n", fileLibraryVersion());
 }
 
+static void cdiPrintDatatypes(void)
+{
+#define XSTRING(x)	#x
+#define STRING(x)	XSTRING(x)
+  fprintf (stderr, "+-------------+-------+\n"
+           "| types       | bytes |\n"
+           "+-------------+-------+\n"
+           "| void *      |   %3d |\n"
+           "+-------------+-------+\n"
+           "| char        |   %3d |\n"
+           "+-------------+-------+\n"
+           "| bool        |   %3d |\n"
+           "| short       |   %3d |\n"
+           "| int         |   %3d |\n"
+           "| long        |   %3d |\n"
+           "| long long   |   %3d |\n"
+           "| size_t      |   %3d |\n"
+           "| off_t       |   %3d |\n"
+           "+-------------+-------+\n"
+           "| float       |   %3d |\n"
+           "| double      |   %3d |\n"
+           "| long double |   %3d |\n"
+           "+-------------+-------+\n\n"
+           "+-------------+-----------+\n"
+           "| INT32       | %-9s |\n"
+           "| INT64       | %-9s |\n"
+           "| FLT32       | %-9s |\n"
+           "| FLT64       | %-9s |\n"
+           "+-------------+-----------+\n"
+           "\n  byte ordering is %s\n\n",
+           (int) sizeof(void *), (int) sizeof(char), (int) sizeof(bool),
+           (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long),
+           (int) sizeof(size_t), (int) sizeof(off_t),
+           (int) sizeof(float), (int) sizeof(double), (int) sizeof(long double),
+           STRING(INT32), STRING(INT64), STRING(FLT32), STRING(FLT64),
+           ((HOST_ENDIANNESS == CDI_BIGENDIAN) ? "BIGENDIAN"
+            : ((HOST_ENDIANNESS == CDI_LITTLEENDIAN) ? "LITTLEENDIAN"
+               : "Unhandled endianness!")));
+#undef STRING
+#undef XSTRING
+}
+
 void cdiDebug(int level)
 {
   if ( level == 1 || (level &  2) ) CDI_Debug = 1;
diff --git a/libcdi/src/cdi_int.h b/libcdi/src/cdi_int.h
index f01011e..728487f 100644
--- a/libcdi/src/cdi_int.h
+++ b/libcdi/src/cdi_int.h
@@ -41,7 +41,7 @@ char *strdup(const char *s);
 #endif
 
 
-#ifndef  _ERROR_H
+#ifndef  ERROR_H
 #  include "error.h"
 #endif
 #ifndef _BASETIME_H
@@ -152,6 +152,14 @@ typedef struct
   int       ilevel2;
   int       ltype;
   short     tsteptype;
+#ifdef HIRLAM_EXTENSIONS
+    // NOTE: tsteptype MUST be part of attributes used to compare variables!
+    // Modern NWP models (HARMONIE, HIRLAM) use timeRangeIndicator to specify
+    // if the field is instantanous or accumulated.
+    // Both types are typically in the same GRIB-file.
+    // (181; 105, 0, timeRangeIndicator=0) .. instantanous rain
+    // (181; 105, 0, timeRangeIndicator=4) .. accumulated rain  .. both can be in the same grib file
+#endif // HIRLAM_EXTENSIONS
   short     used;
   short     varID;
   short     levelID;
@@ -303,6 +311,7 @@ typedef enum {
 #define  CDI_FILETYPE_UNDEF          -1   /* Unknown/not yet defined file type */
 
 
+extern int cdiDebugExt;
 extern int CDI_Debug;      /* If set to 1, debuggig (default 0)            */
 extern int CDI_Recopt;
 extern int cdiGribApiDebug;
@@ -386,8 +395,6 @@ void    recordInitEntry(record_t *record);
 
 void    cdiCheckZaxis(int zaxisID);
 
-void    cdiPrintDatatypes(void);
-
 void    cdiDefAccesstype(int streamID, int type);
 int     cdiInqAccesstype(int streamID);
 
diff --git a/libcdi/src/cdipio.inc b/libcdi/src/cdipio.inc
index 9151a81..f44a62c 100644
--- a/libcdi/src/cdipio.inc
+++ b/libcdi/src/cdipio.inc
@@ -1,40 +1,44 @@
 ! This file was automatically generated, don't edit!
 !
-! Fortran interface for CDI library version 1.7.2
+! Fortran interface for CDI library version 1.8.0
 !
 ! Author:
 ! -------
-! Uwe Schulzweida, MPI-MET, Hamburg,   April 2016
+! Uwe Schulzweida, MPI-MET, Hamburg,   March 2017
 !
 
 !
 !  parallel IO IOMode
 !
-      INTEGER    PIO_NONE              
+      INTEGER    PIO_NONE
       PARAMETER (PIO_NONE               =  0)
-      INTEGER    PIO_MPI               
+      INTEGER    PIO_MPI
       PARAMETER (PIO_MPI                =  1)
-      INTEGER    PIO_WRITER            
+      INTEGER    PIO_WRITER
       PARAMETER (PIO_WRITER             =  2)
-      INTEGER    PIO_ASYNCH            
+      INTEGER    PIO_ASYNCH
       PARAMETER (PIO_ASYNCH             =  3)
-      INTEGER    PIO_FPGUARD           
+      INTEGER    PIO_FPGUARD
       PARAMETER (PIO_FPGUARD            =  4)
-      INTEGER    PIO_MPI_FW_ORDERED    
+      INTEGER    PIO_MPI_FW_ORDERED
       PARAMETER (PIO_MPI_FW_ORDERED     =  5)
-      INTEGER    PIO_MPI_FW_AT_ALL     
+      INTEGER    PIO_MPI_FW_AT_ALL
       PARAMETER (PIO_MPI_FW_AT_ALL      =  6)
-      INTEGER    PIO_MPI_FW_AT_REBLOCK 
+      INTEGER    PIO_MPI_FW_AT_REBLOCK
       PARAMETER (PIO_MPI_FW_AT_REBLOCK  =  7)
-      INTEGER    PIO_ROLE_CLIENT       
+      INTEGER    PIO_MINIOMODE
+      PARAMETER (PIO_MINIOMODE          = PIO_NONE)
+      INTEGER    PIO_MAXIOMODE
+      PARAMETER (PIO_MAXIOMODE          = PIO_MPI_FW_AT_REBLOCK)
+      INTEGER    PIO_ROLE_CLIENT
       PARAMETER (PIO_ROLE_CLIENT        =  0)
-      INTEGER    PIO_ROLE_COLLECTOR    
+      INTEGER    PIO_ROLE_COLLECTOR
       PARAMETER (PIO_ROLE_COLLECTOR     =  1)
-      INTEGER    PIO_ROLE_WRITER       
+      INTEGER    PIO_ROLE_WRITER
       PARAMETER (PIO_ROLE_WRITER        =  2)
       INTEGER    PIO_ROLE_WRITER_COLLECTOR
       PARAMETER (PIO_ROLE_WRITER_COLLECTOR =  3)
-      INTEGER    PIO_ROLE_FPGUARD      
+      INTEGER    PIO_ROLE_FPGUARD
       PARAMETER (PIO_ROLE_FPGUARD       =  4)
 !
 !  parallel IO routines
diff --git a/libcdi/src/cdipioFortran.c b/libcdi/src/cdipioFortran.c
index 522faab..b076ece 100644
--- a/libcdi/src/cdipioFortran.c
+++ b/libcdi/src/cdipioFortran.c
@@ -11,7 +11,19 @@
 #if defined (HAVE_CF_INTERFACE)
 
 #if ! defined (__CFORTRAN_LOADED)
+#  if defined __clang__
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wreserved-id-macro"
+#  endif
 #  include "cfortran.h"
+#  if defined __clang__
+#    pragma GCC diagnostic pop
+#  endif
+#endif
+/* These functions are meant to be called from Fortran and don't
+ * need an interface declaration in a C header. */
+#if defined __clang__
+#  pragma GCC diagnostic ignored "-Wmissing-prototypes"
 #endif
 
 
@@ -48,7 +60,7 @@ static void streamWriteVarPart_fwrap(int streamID, int varID, const void *data,
   streamWriteVarPart(streamID, varID, data, nmiss, (*(Xt_idxlist *)partDesc));
 }
 FCALLSCSUB5 (streamWriteVarPart_fwrap, STREAMWRITEVARPART, streamwritevarpart, INT, INT, PVOID, INT, PVOID)
-static void streamWriteScatteredVarPart_fwrap(int streamID, int varID, const void *data, int numBlocks, int  blocklengths[], int  displacements[], int nmiss, void *partDesc)
+static void streamWriteScatteredVarPart_fwrap(int streamID, int varID, const void *data, int numBlocks, const int  blocklengths[], const int  displacements[], int nmiss, void *partDesc)
 {
   streamWriteScatteredVarPart(streamID, varID, data, numBlocks, blocklengths, displacements, nmiss, (*(Xt_idxlist *)partDesc));
 }
@@ -106,4 +118,7 @@ FCALLSCSUB2 (cdiPioConfSetStripeConversion, CDIPIOCONFSETSTRIPECONVERSION, cdipi
 
 FCALLSCFUN1 (INT, cdiPioConfGetStripeConversion, CDIPIOCONFGETSTRIPECONVERSION, cdipioconfgetstripeconversion, INT)
 
+#if defined __clang__
+#  pragma GCC diagnostic pop
+#endif
 #endif
diff --git a/libcdi/src/cfortran.h b/libcdi/src/cfortran.h
index 275b8cf..222faba 100644
--- a/libcdi/src/cfortran.h
+++ b/libcdi/src/cfortran.h
@@ -591,7 +591,7 @@ if (e>s) {                           /* Need this to handle NULL string.*/
 } return s; }
 
 #ifndef __CF__KnR
-static int num_elem(char *strv, unsigned elem_len, int term_char, int num_term);
+static int num_elem(const char *strv, unsigned elem_len, int term_char, int num_term);
 #endif
 /* kill_trailingn(s,t,e) will kill the trailing t's in string s. e normally 
 points to the terminating '\0' of s, but may actually point to anywhere in s.
@@ -608,8 +608,7 @@ else if (e>s) {                      /* Watch out for neg. length string.*/
   while (e>s && *--e==t){;}          /* Don't follow t's past beginning. */
   e[*e==t?0:1] = '\0';               /* Handle s[0]=t correctly.       */
 }
-if (0)  /* to prevent not used warnings in gcc (added by TJ) */
-  num_elem("", 0, '\0', 1);
+(void)num_elem;  /* to prevent not used warnings in gcc (added by TJ) */
 
  return s; }
 
@@ -659,7 +658,7 @@ typedef DSC$DESCRIPTOR_A(1) fstringvector;
 #define NUM_ELEM_ARG(B) *_2(A,B),_NUM_ELEM_ARG
 #define TERM_CHARS(A,B) A,B
 #ifndef __CF__KnR
-static int num_elem(char *strv, unsigned elem_len, int term_char, int num_term)
+static int num_elem(const char *strv, unsigned elem_len, int term_char, int num_term)
 #else
 static int num_elem(      strv,          elem_len,     term_char,     num_term)
                     char *strv; unsigned elem_len; int term_char; int num_term;
@@ -678,10 +677,10 @@ for (num=0; ; num++) {
   if (i==(unsigned)num_term) break;
   else strv += elem_len-i;
 }
-if (0) {  /* to prevent not used warnings in gcc (added by ROOT) */
-   c2fstrv(0, 0, 0, 0); f2cstrv(0, 0, 0, 0); kill_trailing(0, 0);
-   vkill_trailing(0, 0, 0, 0); num_elem(0, 0, 0, 0);
-}
+/* to prevent not used warnings in gcc (added by ROOT, changed by TJ
+ * because of unreachable warnings from clang) */
+(void)c2fstrv; (void)f2cstrv; (void)kill_trailing;
+(void)vkill_trailing; (void)num_elem;
 return (int)num;
 }
 /* #endif removed 2/10/98 (CFITSIO) */
diff --git a/libcdi/src/cgribexlib.c b/libcdi/src/cgribexlib.c
index d7a0ad3..bd84f03 100644
--- a/libcdi/src/cgribexlib.c
+++ b/libcdi/src/cgribexlib.c
@@ -54,7 +54,7 @@
 #if ! defined   (_CGRIBEX_H)
 #  include "cgribex.h"
 #endif
-#if ! defined   (_ERROR_H)
+#if ! defined   (ERROR_H)
 #  include "error.h"
 #endif
 #if ! defined   (_DTYPES_H)
diff --git a/libcdi/src/config.h.in b/libcdi/src/config.h.in
index 8c9bcb7..3110e95 100644
--- a/libcdi/src/config.h.in
+++ b/libcdi/src/config.h.in
@@ -205,6 +205,9 @@
 /* yaxt library is available */
 #undef HAVE_YAXT
 
+/* Define to 1 for HIRLAM extensions */
+#undef HIRLAM_EXTENSIONS
+
 /* Host name */
 #undef HOST_NAME
 
diff --git a/libcdi/src/error.h b/libcdi/src/error.h
index 58b7288..28ccc6c 100644
--- a/libcdi/src/error.h
+++ b/libcdi/src/error.h
@@ -1,5 +1,5 @@
-#ifndef _ERROR_H
-#define _ERROR_H
+#ifndef ERROR_H
+#define ERROR_H
 
 #include <stdarg.h>
 #include <stdlib.h>
@@ -70,7 +70,7 @@ cdiAbortC_serial(const char *caller, const char *filename,
 }
 #endif
 
-#endif  /* _ERROR_H */
+#endif  /* ERROR_H */
 /*
  * Local Variables:
  * c-file-style: "Java"
diff --git a/libcdi/src/file.c b/libcdi/src/file.c
index 4ea2e81..76cc0db 100644
--- a/libcdi/src/file.c
+++ b/libcdi/src/file.c
@@ -6,9 +6,11 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
-#include <stdint.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -47,14 +49,6 @@ char *strdup(const char *s);
 #endif
 
 
-#if ! defined   (FALSE)
-#  define  FALSE  0
-#endif
-
-#if ! defined   (TRUE)
-#  define  TRUE   1
-#endif
-
 /* #define  MAX_FILES  FOPEN_MAX */
 #define  MAX_FILES  4096
 
@@ -62,7 +56,7 @@ static int _file_max = MAX_FILES;
 
 static void file_initialize(void);
 
-static int _file_init = FALSE;
+static bool _file_init = false;
 
 #if  defined  (HAVE_LIBPTHREAD)
 #include <pthread.h>
@@ -73,14 +67,14 @@ static pthread_mutex_t _file_mutex;
 #  define FILE_LOCK()         pthread_mutex_lock(&_file_mutex)
 #  define FILE_UNLOCK()       pthread_mutex_unlock(&_file_mutex)
 #  define FILE_INIT()        \
-   if ( _file_init == FALSE ) pthread_once(&_file_init_thread, file_initialize)
+   if ( _file_init == false ) pthread_once(&_file_init_thread, file_initialize)
 
 #else
 
 #  define FILE_LOCK()
 #  define FILE_UNLOCK()
 #  define FILE_INIT()        \
-   if ( _file_init == FALSE ) file_initialize()
+   if ( _file_init == false ) file_initialize()
 
 #endif
 
@@ -125,7 +119,7 @@ enum F_I_L_E_Flags
   };
 
 
-static int FileInfo  = FALSE;
+static bool FileInfo = false;
 
 
 #if ! defined (MIN_BUF_SIZE)
@@ -150,7 +144,7 @@ static void file_table_print(void);
  * A version string.
  */
 #undef   LIBVERSION
-#define  LIBVERSION      1.8.2
+#define  LIBVERSION      1.8.3
 #define  XSTRING(x)	 #x
 #define  STRING(x) 	 XSTRING(x)
 static const char file_libvers[] = STRING(LIBVERSION) " of " __DATE__ " " __TIME__;
@@ -190,7 +184,7 @@ void file_list_new(void)
 {
   assert(_fileList == NULL);
 
-  _fileList = (filePtrToIdx *) Malloc((size_t)_file_max * sizeof (filePtrToIdx));
+  _fileList = (filePtrToIdx *) Malloc((size_t)_file_max*sizeof(filePtrToIdx));
 }
 
 static
@@ -206,9 +200,7 @@ void file_list_delete(void)
 static
 void file_init_pointer(void)
 {
-  int  i;
-
-  for ( i = 0; i < _file_max; i++ )
+  for ( int i = 0; i < _file_max; i++ )
     {
       _fileList[i].next = _fileList + i + 1;
       _fileList[i].idx  = i;
@@ -238,14 +230,14 @@ bfile_t *file_to_pointer(int idx)
   else
     Error("file index %d undefined!", idx);
 
-  return (fileptr);
+  return fileptr;
 }
 
 /* Create an index from a pointer */
 static
 int file_from_pointer(bfile_t *ptr)
 {
-  int      idx = -1;
+  int idx = -1;
   filePtrToIdx *newptr;
 
   if ( ptr )
@@ -271,7 +263,7 @@ int file_from_pointer(bfile_t *ptr)
   else
     Error("Internal problem (pointer %p undefined)", ptr);
 
-  return (idx);
+  return idx;
 }
 
 static
@@ -305,21 +297,16 @@ void file_init_entry(bfile_t *fileptr)
 static
 bfile_t *file_new_entry(void)
 {
-  bfile_t *fileptr;
-
-  fileptr = (bfile_t *) Malloc(sizeof(bfile_t));
-
+  bfile_t *fileptr = (bfile_t *) Malloc(sizeof(bfile_t));
   if ( fileptr ) file_init_entry(fileptr);
 
-  return (fileptr);
+  return fileptr;
 }
 
 static
 void file_delete_entry(bfile_t *fileptr)
 {
-  int idx;
-
-  idx = fileptr->self;
+  int idx = fileptr->self;
 
   FILE_LOCK();
 
@@ -338,49 +325,41 @@ void file_delete_entry(bfile_t *fileptr)
 
 const char *fileLibraryVersion(void)
 {
-  return (file_libvers);
+  return file_libvers;
 }
 
-
 static
 int pagesize(void)
 {
 #if defined(_SC_PAGESIZE)
-  return ((int) sysconf(_SC_PAGESIZE));
+  return (int) sysconf(_SC_PAGESIZE);
 #else
 #ifndef POSIXIO_DEFAULT_PAGESIZE
 #define POSIXIO_DEFAULT_PAGESIZE 4096
 #endif
-  return ((int) POSIXIO_DEFAULT_PAGESIZE);
+  return (int) POSIXIO_DEFAULT_PAGESIZE;
 #endif
 }
 
 static
 double file_time()
 {
-  double tseconds = 0.0;
   struct timeval mytime;
   gettimeofday(&mytime, NULL);
-  tseconds = (double) mytime.tv_sec + (double) mytime.tv_usec*1.0e-6;
-  return (tseconds);
+  double tseconds = (double) mytime.tv_sec + (double) mytime.tv_usec*1.0e-6;
+  return tseconds;
 }
 
 void fileDebug(int debug)
 {
   FILE_Debug = debug;
-
-  if ( FILE_Debug )
-    Message("Debug level %d", debug);
+  if ( FILE_Debug ) Message("Debug level %d", debug);
 }
 
 
 void *filePtr(int fileID)
 {
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
-
-  return (fileptr);
+  return (void*)file_to_pointer(fileID);
 }
 
 static
@@ -398,9 +377,7 @@ void file_pointer_info(const char *caller, int fileID)
 int fileSetBufferType(int fileID, int type)
 {
   int ret = 0;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( fileptr )
     {
@@ -419,27 +396,22 @@ int fileSetBufferType(int fileID, int type)
   if ( type == FILE_BUFTYPE_MMAP ) ret = 1;
 #endif
 
-  return (ret);
+  return ret;
 }
 
 int fileFlush(int fileID)
 {
-  bfile_t *fileptr;
   int retval = 0;
-
-  fileptr = file_to_pointer(fileID);
-
+  bfile_t *fileptr = file_to_pointer(fileID);
   if ( fileptr ) retval = fflush(fileptr->fp);
 
-  return (retval);
+  return retval;
 }
 
 
 void fileClearerr(int fileID)
 {
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( fileptr )
     {
@@ -451,25 +423,21 @@ void fileClearerr(int fileID)
 
 int filePtrEOF(void *vfileptr)
 {
-  bfile_t *fileptr = (bfile_t *) vfileptr;
   int retval = 0;
-
+  bfile_t *fileptr = (bfile_t *) vfileptr;
   if ( fileptr ) retval = (fileptr->flag & FILE_EOF) != 0;
 
-  return (retval);
+  return retval;
 }
 
 
 int fileEOF(int fileID)
 {
-  bfile_t *fileptr;
   int retval = 0;
-
-  fileptr = file_to_pointer(fileID);
-
+  bfile_t *fileptr = file_to_pointer(fileID);
   if ( fileptr ) retval = (fileptr->flag & FILE_EOF) != 0;
 
-  return (retval);
+  return retval;
 }
 
 void fileRewind(int fileID)
@@ -482,9 +450,7 @@ void fileRewind(int fileID)
 off_t fileGetPos(int fileID)
 {
   off_t filepos = 0;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( fileptr )
     {
@@ -496,23 +462,21 @@ off_t fileGetPos(int fileID)
 
   if ( FILE_Debug ) Message("Position %ld", filepos);
 
-  return (filepos);
+  return filepos;
 }
 
 
 int fileSetPos(int fileID, off_t offset, int whence)
 {
   int status = 0;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( FILE_Debug ) Message("Offset %8ld  Whence %3d", (long) offset, whence);
 
   if ( fileptr == 0 )
     {
       file_pointer_info(__func__, fileID);
-      return (1);
+      return 1;
     }
 
   switch (whence)
@@ -593,19 +557,17 @@ int fileSetPos(int fileID, off_t offset, int whence)
     if ( (fileptr->flag & FILE_EOF) != 0 )
       fileptr->flag -= FILE_EOF;
 
-  return (status);
+  return status;
 }
 
 static
 void file_table_print(void)
 {
-  int fileID;
   int lprintHeader = 1;
-  bfile_t *fileptr;
 
-  for ( fileID = 0; fileID < _file_max; fileID++ )
+  for ( int fileID = 0; fileID < _file_max; fileID++ )
     {
-      fileptr = file_to_pointer(fileID);
+      bfile_t *fileptr = file_to_pointer(fileID);
 
       if ( fileptr )
 	{
@@ -652,43 +614,34 @@ void file_table_print(void)
 
 char *fileInqName(int fileID)
 {
-  bfile_t *fileptr;
   char *name = NULL;
-
-  fileptr = file_to_pointer(fileID);
-
+  bfile_t *fileptr = file_to_pointer(fileID);
   if ( fileptr ) name = fileptr->name;
 
-  return (name);
+  return name;
 }
 
 
 int fileInqMode(int fileID)
 {
-  bfile_t *fileptr;
   int mode = 0;
-
-  fileptr = file_to_pointer(fileID);
-
+  bfile_t *fileptr = file_to_pointer(fileID);
   if ( fileptr ) mode = fileptr->mode;
 
-  return (mode);
+  return mode;
 }
 
 static
 long file_getenv(const char *envName)
 {
-  char *envString;
   long envValue = -1;
   long fact = 1;
 
-  envString = getenv(envName);
+  char *envString = getenv(envName);
 
   if ( envString )
     {
-      int loop;
-
-      for ( loop = 0; loop < (int) strlen(envString); loop++ )
+      for ( int loop = 0; loop < (int) strlen(envString); loop++ )
 	{
 	  if ( ! isdigit((int) envString[loop]) )
 	    {
@@ -711,14 +664,13 @@ long file_getenv(const char *envName)
       if ( FILE_Debug ) Message("Set %s to %ld", envName, envValue);
     }
 
-  return (envValue);
+  return envValue;
 }
 
 static
 void file_initialize(void)
 {
   long value;
-  char *envString;
 
 #if  defined  (HAVE_LIBPTHREAD)
   /* initialize global API mutex lock */
@@ -734,7 +686,7 @@ void file_initialize(void)
   if ( FILE_Debug )
     Message("FILE_MAX = %d", _file_max);
 
-  FileInfo  = (int) file_getenv("FILE_INFO");
+  FileInfo = file_getenv("FILE_INFO") > 0;
 
   value  = file_getenv("FILE_BUFSIZE");
   if ( value >= 0 ) FileBufferSizeEnv = value;
@@ -775,7 +727,7 @@ void file_initialize(void)
 #if defined (O_NONBLOCK)
   FileFlagWrite = O_NONBLOCK;
 #endif
-  envString = getenv("FILE_FLAG_WRITE");
+  char *envString = getenv("FILE_FLAG_WRITE");
   if ( envString )
     {
 #if defined (O_NONBLOCK)
@@ -815,7 +767,7 @@ void file_initialize(void)
 
   if ( FILE_Debug ) atexit(file_table_print);
 
-  _file_init = TRUE;
+  _file_init = true;
 }
 
 static
@@ -891,20 +843,18 @@ static
 int file_fill_buffer(bfile_t *fileptr)
 {
   ssize_t nread;
-  int fd;
   long offset = 0;
-  off_t retseek;
 
   if ( FILE_Debug )
     Message("file ptr = %p  Cnt = %ld", fileptr, fileptr->bufferCnt);
 
-  if ( (fileptr->flag & FILE_EOF) != 0 ) return (EOF);
+  if ( (fileptr->flag & FILE_EOF) != 0 ) return EOF;
 
   if ( fileptr->buffer == NULL ) file_set_buffer(fileptr);
 
-  if ( fileptr->bufferSize == 0 ) return (EOF);
+  if ( fileptr->bufferSize == 0 ) return EOF;
 
-  fd = fileptr->fd;
+  int fd = fileptr->fd;
 
 #if defined (HAVE_MMAP)
   if ( fileptr->bufferType == FILE_BUFTYPE_MMAP )
@@ -915,15 +865,14 @@ int file_fill_buffer(bfile_t *fileptr)
 	}
       else
 	{
-          xassert(fileptr->bufferSize <= SIZE_MAX);
+          xassert(fileptr->bufferSize <= SSIZE_MAX);
 	  nread = (ssize_t)fileptr->bufferSize;
 	  if ( (nread + fileptr->bufferPos) > fileptr->size )
 	    nread = fileptr->size - fileptr->bufferPos;
 
 	  if ( fileptr->buffer )
 	    {
-              int ret;
-	      ret = munmap(fileptr->buffer, fileptr->mappedSize);
+              int ret = munmap(fileptr->buffer, fileptr->mappedSize);
 	      if ( ret == -1 ) SysError("munmap error for read %s", fileptr->name);
 	      fileptr->buffer = NULL;
 	    }
@@ -940,22 +889,19 @@ int file_fill_buffer(bfile_t *fileptr)
   else
 #endif
     {
-      retseek = lseek(fileptr->fd, fileptr->bufferPos, SEEK_SET);
+      off_t retseek = lseek(fileptr->fd, fileptr->bufferPos, SEEK_SET);
       if ( retseek == (off_t)-1 )
 	SysError("lseek error at pos %ld file %s", (long) fileptr->bufferPos, fileptr->name);
 
       nread = read(fd, fileptr->buffer, fileptr->bufferSize);
+      if ( nread > 0 ) offset = fileptr->position - fileptr->bufferPos;
     }
 
   if ( nread <= 0 )
     {
-      if ( nread == 0 )
-	fileptr->flag |= FILE_EOF;
-      else
-	fileptr->flag |= FILE_ERROR;
-
+      fileptr->flag |= (nread == 0) ? FILE_EOF : FILE_ERROR;
       fileptr->bufferCnt = 0;
-      return (EOF);
+      return EOF;
     }
 
   fileptr->bufferPtr = fileptr->buffer;
@@ -987,7 +933,7 @@ int file_fill_buffer(bfile_t *fileptr)
 
   fileptr->bufferNumFill++;
 
-  return ((unsigned char) *fileptr->bufferPtr);
+  return (unsigned char) *fileptr->bufferPtr;
 }
 
 static
@@ -1018,7 +964,7 @@ void file_copy_from_buffer(bfile_t *fileptr, void *ptr, size_t size)
 static
 size_t file_read_from_buffer(bfile_t *fileptr, void *ptr, size_t size)
 {
-  size_t nread, rsize;
+  size_t nread;
   size_t offset = 0;
 
   if ( FILE_Debug )
@@ -1027,7 +973,7 @@ size_t file_read_from_buffer(bfile_t *fileptr, void *ptr, size_t size)
   if ( ((long)fileptr->bufferCnt) < 0L )
     Error("Internal problem. bufferCnt = %ld", (long) fileptr->bufferCnt);
 
-  rsize = size;
+  size_t rsize = size;
 
   while ( fileptr->bufferCnt < rsize )
     {
@@ -1080,13 +1026,12 @@ int fileOpen_serial(const char *filename, const char *mode)
   FILE *fp = NULL;    /* file pointer    (used for write) */
   int fd = -1;        /* file descriptor (used for read)  */
   int fileID = FILE_UNDEFID;
-  int fmode = 0;
   struct stat filestat;
   bfile_t *fileptr = NULL;
 
   FILE_INIT();
 
-  fmode = tolower((int) mode[0]);
+  int fmode = tolower((int) mode[0]);
 
   switch ( fmode )
     {
@@ -1113,7 +1058,7 @@ int fileOpen_serial(const char *filename, const char *mode)
 
   if ( fp )
     {
-      if ( stat(filename, &filestat) != 0 ) return (fileID);
+      if ( stat(filename, &filestat) != 0 ) return fileID;
 
       fileptr = file_new_entry();
       if ( fileptr )
@@ -1124,7 +1069,7 @@ int fileOpen_serial(const char *filename, const char *mode)
     }
   else if ( fd >= 0 )
     {
-      if ( fstat(fd, &filestat) != 0 ) return (fileID);
+      if ( fstat(fd, &filestat) != 0 ) return fileID;
 
       fileptr = file_new_entry();
       if ( fileptr )
@@ -1160,7 +1105,7 @@ int fileOpen_serial(const char *filename, const char *mode)
 	Message("File %s opened with ID %d", filename, fileID);
     }
 
-  return (fileID);
+  return fileID;
 }
 
 /*
@@ -1175,7 +1120,6 @@ int fileClose(int fileID)
 
 int fileClose_serial(int fileID)
 {
-  char *name;
   int ret;
   const char *fbtname[] = {"unknown", "standard", "mmap"};
   const char *ftname[] = {"unknown", "open", "fopen"};
@@ -1185,15 +1129,15 @@ int fileClose_serial(int fileID)
   if ( fileptr == NULL )
     {
       file_pointer_info(__func__, fileID);
-      return (1);
+      return 1;
     }
 
-  name = fileptr->name;
+  char *name = fileptr->name;
 
   if ( FILE_Debug )
     Message("fileID = %d  filename = %s", fileID, name);
 
-  if ( FileInfo > 0 )
+  if ( FileInfo )
     {
       fprintf(stderr, "____________________________________________\n");
       fprintf(stderr, " file ID          : %d\n",  fileID);
@@ -1232,9 +1176,7 @@ int fileClose_serial(int fileID)
 	}
 
       if ( fileptr->time_in_sec > 0 )
-        {
-          rout = (double)fileptr->byteTrans / (1024.*1024.*fileptr->time_in_sec);
-        }
+        rout = (double)fileptr->byteTrans / (1024.*1024.*fileptr->time_in_sec);
 
       fprintf(stderr, " wall time [s]    : %.2f\n", fileptr->time_in_sec);
       fprintf(stderr, " data rate [MB/s] : %.1f\n", rout);
@@ -1277,22 +1219,20 @@ int fileClose_serial(int fileID)
 
   file_delete_entry(fileptr);
 
-  return (0);
+  return 0;
 }
 
 
 int filePtrGetc(void *vfileptr)
 {
   int ivalue = EOF;
-  int fillret = 0;
   bfile_t *fileptr = (bfile_t *) vfileptr;
 
   if ( fileptr )
     {
       if ( fileptr->mode == 'r' && fileptr->type == FILE_TYPE_OPEN )
 	{
-	  if ( fileptr->bufferCnt == 0 ) fillret = file_fill_buffer(fileptr);
-
+	  int fillret = (fileptr->bufferCnt == 0) ? file_fill_buffer(fileptr) : 0;
 	  if ( fillret >= 0 )
 	    {
 	      ivalue = (unsigned char) *fileptr->bufferPtr++;
@@ -1316,20 +1256,14 @@ int filePtrGetc(void *vfileptr)
 	}
     }
 
-  return (ivalue);
+  return ivalue;
 }
 
 
 int fileGetc(int fileID)
 {
-  int ivalue;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
-
-  ivalue = filePtrGetc((void *)fileptr);
-
-  return (ivalue);
+  bfile_t *fileptr = file_to_pointer(fileID);
+  return filePtrGetc((void *)fileptr);
 }
 
 
@@ -1346,12 +1280,7 @@ size_t filePtrRead(void *vfileptr, void *restrict ptr, size_t size)
 	{
 	  nread = fread(ptr, 1, size, fileptr->fp);
 	  if ( nread != size )
-	    {
-	      if ( nread == 0 )
-		fileptr->flag |= FILE_EOF;
-	      else
-		fileptr->flag |= FILE_ERROR;
-	    }
+            fileptr->flag |= (nread == 0) ? FILE_EOF : FILE_ERROR;
 	}
 
       fileptr->position  += (off_t)nread;
@@ -1361,16 +1290,14 @@ size_t filePtrRead(void *vfileptr, void *restrict ptr, size_t size)
 
   if ( FILE_Debug ) Message("size %ld  nread %ld", size, nread);
 
-  return (nread);
+  return nread;
 }
 
 
 size_t fileRead(int fileID, void *restrict ptr, size_t size)
 {
   size_t nread = 0;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( fileptr )
     {
@@ -1401,23 +1328,19 @@ size_t fileRead(int fileID, void *restrict ptr, size_t size)
 
   if ( FILE_Debug ) Message("size %ld  nread %ld", size, nread);
 
-  return (nread);
+  return nread;
 }
 
 
 size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
 {
   size_t nwrite = 0;
-  bfile_t *fileptr;
-
-  fileptr = file_to_pointer(fileID);
+  bfile_t *fileptr = file_to_pointer(fileID);
 
   if ( fileptr )
     {
       double t_begin = 0.0;
 
-      /* if ( fileptr->buffer == NULL ) file_set_buffer(fileptr); */
-
       if ( FileInfo ) t_begin = file_time();
 
       if ( fileptr->type == FILE_TYPE_FOPEN )
@@ -1441,7 +1364,7 @@ size_t fileWrite(int fileID, const void *restrict ptr, size_t size)
       fileptr->access++;
     }
 
-  return (nwrite);
+  return nwrite;
 }
 /*
  * Local Variables:
diff --git a/libcdi/src/grb_read.c b/libcdi/src/grb_read.c
index 2c1bc98..787dd65 100644
--- a/libcdi/src/grb_read.c
+++ b/libcdi/src/grb_read.c
@@ -12,7 +12,6 @@
 #include "stream_gribapi.h"
 #include "file.h"
 #include "cgribex.h"  /* gribZip gribGetZip gribGinfo */
-#include "gribapi.h"
 #include "namespace.h"
 
 
diff --git a/libcdi/src/grb_write.c b/libcdi/src/grb_write.c
index 6477635..c868ac6 100644
--- a/libcdi/src/grb_write.c
+++ b/libcdi/src/grb_write.c
@@ -7,12 +7,12 @@
 #include "dmemory.h"
 #include "cdi.h"
 #include "cdi_int.h"
+#include "gribapi.h"
 #include "stream_cgribex.h"
 #include "stream_grb.h"
 #include "stream_gribapi.h"
 #include "file.h"
 #include "cgribex.h"  /* gribZip gribGetZip gribGinfo */
-#include "gribapi.h"
 #include "namespace.h"
 
 
@@ -118,6 +118,89 @@ void grbCopyRecord(stream_t * streamptr2, stream_t * streamptr1)
 
   if ( filetype == CDI_FILETYPE_GRB )
     {
+      if ( cdiGribChangeParameterID.active )
+        {
+          // Even if you are stream-copy records you might need to change a bit of grib-header !
+#if defined HAVE_LIBCGRIBEX
+          void *gh = cgribex_handle_new_from_meassage((void*) gribbuffer, recsize);
+          cgribexChangeParameterIdentification(gh, cdiGribChangeParameterID.code, cdiGribChangeParameterID.ltype, cdiGribChangeParameterID.lev);
+          cgribex_handle_delete(gh);
+#elif defined HAVE_LIBGRIB_API
+          void *gh = (void*)grib_handle_new_from_message(NULL, (void*) gribbuffer, recsize);
+          gribapiChangeParameterIdentification(gh, cdiGribChangeParameterID.code, cdiGribChangeParameterID.ltype, cdiGribChangeParameterID.lev);
+          grib_handle_delete(gh);
+#endif
+          cdiGribChangeParameterID.active = false; // after grib attributes have been changed turn it off again
+        }
+    }
+
+#ifdef HIRLAM_EXTENSIONS
+  // Even if you are stream-copy records you might need to change a bit of grib-header !
+
+  if ( cdiGribDataScanningMode.active )
+    // allowed modes: <0, 64, 96>; Default is 64
+    // This will overrule the old scanning mode of the given grid
+  {
+    grib_handle *gh = NULL;
+    gh = grib_handle_new_from_message(NULL, (void *) gribbuffer, recsize);
+
+    int scanModeIN = gribapiGetScanningMode(gh);
+
+    grib_handle_delete(gh);
+
+    if (cdiDebugExt>=20) Message("Change GribDataScanningMode => %d (scanModeIN = %d)", cdiGribDataScanningMode.value, scanModeIN);
+
+    if (scanModeIN != cdiGribDataScanningMode.value)
+    {
+        int gridID;
+        int varID, levelID;
+        int vlistID;
+        //int zip;
+        int gridsize, nmiss = 0;
+
+        vlistID = streamptr1->vlistID;
+        varID   = streamptr1->tsteps[tsID].records[recID].varID;
+        levelID   = streamptr1->tsteps[tsID].records[recID].levelID;
+        //gribbuffer = (unsigned char *) streamptr->record->buffer;
+        // allocate above ..
+        gridID   = vlistInqVarGrid(vlistID, varID);
+        gridsize = gridInqSize(gridID);
+
+        gridsize = vlistGridsizeMax(vlistID);
+        if ( vlistNumber(vlistID) != CDI_REAL ) gridsize *= 2;
+        double * data = (double *) malloc(gridsize*sizeof(double));
+        //int missval = vlistInqVarMissval(vlistID, varID);
+
+        //streamptr->numvals += gridsize;
+
+        // memtype: MEMTYPE_FLOAT or MEMTYPE_DOUBLE
+        //int statusDC = grbDecode(filetype, MEMTYPE_DOUBLE, gribbuffer, recsize, data, gridsize, streamptr1->unreduced, &nmiss, missval, vlistID, varID);
+        //int grbDecode(int filetype, int memtype, void *gribbuffer, int gribsize, void *data, size_t datasize,
+        //              int unreduced, int *nmiss, double missval, int vlistID, int varID);
+
+        //streamptr1->tsteps[tsID].records[recID].zip = zip;
+        //gribapiSetScanningMode(gh, cdoGribDataScanningMode);  // T.B.D. this will be done by grbDecode..
+
+        //varID   = streamptr1->record->varID;
+        //levelID = streamptr1->record->levelID;
+
+        if (cdiDebugExt>=20) Message(" processing varID %d; levelID %d",varID,levelID);
+
+        grb_write_var_slice(streamptr2, varID, levelID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+        //grb_write_var_slice(streamptr, varID, levelID, memtype, ((double*)data)+levelID*gridsize, nmiss);
+
+        //grb_write_var(streamptr2, varID, MEMTYPE_DOUBLE, data, nmiss);
+        //grb_write_var(stream_t *streamptr, int varID, int memtype, const void *data, int nmiss)
+        //grb_write_var_slice(streamptr2, varID, levelID, MEMTYPE_DOUBLE, (const void *) data, nmiss);
+
+        free(data);
+        free(gribbuffer);
+    }
+  }
+#endif // HIRLAM_EXTENSIONS
+
+  if ( filetype == CDI_FILETYPE_GRB )
+    {
       size_t unzipsize;
       int izip = gribGetZip(recsize, gribbuffer, &unzipsize);
 
@@ -153,9 +236,7 @@ void grb_write_var_slice(stream_t *streamptr, int varID, int levelID, int memtyp
   int tsID      = streamptr->curTsID;
   int date      = streamptr->tsteps[tsID].taxis.vdate;
   int time      = streamptr->tsteps[tsID].taxis.vtime;
-  int numavg    = 0;
-  if ( vlistInqVarTimave(vlistID, varID) )
-    numavg = streamptr->tsteps[tsID].taxis.numavg;
+  int numavg    = (tsteptype == TSTEP_AVG) ? streamptr->tsteps[tsID].taxis.numavg : 0;
 
   if ( CDI_Debug )
     Message("gridID = %d zaxisID = %d", gridID, zaxisID);
diff --git a/libcdi/src/gribapi.h b/libcdi/src/gribapi.h
index 0a1db9a..57d0780 100644
--- a/libcdi/src/gribapi.h
+++ b/libcdi/src/gribapi.h
@@ -3,7 +3,7 @@
 
 #ifdef HAVE_LIBGRIB_API
 #include <grib_api.h>
-#ifndef  _ERROR_H
+#ifndef  ERROR_H
 #include "error.h"
 #endif
 #endif
diff --git a/libcdi/src/gribapi_utilities.c b/libcdi/src/gribapi_utilities.c
index fffb30a..5619f4d 100644
--- a/libcdi/src/gribapi_utilities.c
+++ b/libcdi/src/gribapi_utilities.c
@@ -28,28 +28,29 @@
 //A simple wrapper for grib_get_string() that returns a newly allocated string.
 char* gribCopyString(grib_handle* gribHandle, const char* key)
 {
-  char* result = NULL;
   size_t length;
 #ifdef HAVE_GRIB_GET_LENGTH
-  if(!grib_get_length(gribHandle, key, &length))
+  if (!grib_get_length(gribHandle, key, &length))
     {
-    char* result = (char *) Malloc(length);
-    if(!grib_get_string(gribHandle, key, result, &length))
-    result = (char *) Realloc(result, length);
-
-    else
-      {
+      char *result = (char *)Malloc(length);
+      if (!grib_get_string(gribHandle, key, result, &length))
+        result = (char *) Realloc(result, length);
+      else
+        {
           Free(result);
           result = NULL;
-      }
+        }
+      return result;
     }
+  else
+    return NULL;
 #else
   length = 1024;         /* there's an implementation limit
                           * that makes strings longer than
                           * this unlikely in grib_api versions
                           * not providing grib_get_length */
   int rc;
-  result = (char *) Malloc(length);
+  char *result = (char *) Malloc(length);
   while ((rc = grib_get_string(gribHandle, key, result, &length))
          == GRIB_BUFFER_TOO_SMALL || rc == GRIB_ARRAY_TOO_SMALL)
     {
@@ -68,8 +69,8 @@ char* gribCopyString(grib_handle* gribHandle, const char* key)
       Free(result);
       result = NULL;
     }
-#endif
   return result;
+#endif
 }
 
 //A simple wrapper for grib_get_string() for the usecase that the result is only compared to a given constant string.
@@ -122,8 +123,8 @@ long gribGetLong(grib_handle* gh, const char* key)
 long gribGetLongDefault(grib_handle* gribHandle, const char* key, long defaultValue)
 {
   long result;
-  if(grib_get_long(gribHandle, key, &result)) return defaultValue;
-  if(result == GRIB_MISSING_LONG) return defaultValue;
+  if ( grib_get_long(gribHandle, key, &result) || result == GRIB_MISSING_LONG )
+    result = defaultValue;
   return result;
 }
 
@@ -139,8 +140,9 @@ double gribGetDouble(grib_handle* gh, const char* key)
 double gribGetDoubleDefault(grib_handle* gribHandle, const char* key, double defaultValue)
 {
   double result;
-  if(grib_get_double(gribHandle, key, &result)) return defaultValue;
-  if(IS_EQUAL(result, GRIB_MISSING_DOUBLE)) return defaultValue;
+  if ( grib_get_double(gribHandle, key, &result)
+       || IS_EQUAL(result, GRIB_MISSING_DOUBLE) )
+    result = defaultValue;
   return result;
 }
 
@@ -380,6 +382,48 @@ int gribapiGetTsteptype(grib_handle *gh)
 
           // printf("stepType: %s %ld %d\n", stepType, len, tsteptype);
         }
+#ifdef HIRLAM_EXTENSIONS
+      {
+      // Normaly cdo looks in grib for attribute called "stepType", see above.
+      // BUT NWP models such as Hirlam and Harmonie 37h1.2, use "timeRangeIndicator" instead!
+      // Where for example:       0: for instanteneous fields; 4: for accumulated fields
+      //  0:   Forecast product valid at reference time + P1
+      //  2:   Product with a valid time ranging between reference time + P1 and reference time + P2
+      //  4:   Accumulation (reference time + P1 to reference time + P2)
+      //  5:   Difference(reference time + P2 minus reference time + P1) product considered valid at reference time + P2
+      // More details on WMO standards:
+      //               http://www.wmo.int/pages/prog/www/WDM/Guides/Guide-binary-2.html
+      //tsteptype = TSTEP_INSTANT;  // default value for any case
+      long timeRangeIND = 0; // typically 0: for instanteneous fields; 4: for accumulated fields
+      int rc = grib_get_long(gh, "timeRangeIndicator", &timeRangeIND);
+      if (rc != 0) {
+            //if ( lprint )
+            Warning("Could not get 'stepType' either 'timeRangeIndicator'. Using defualt!");
+            return (tsteptype);
+      }
+      extern int cdiGribUseTimeRangeIndicator;
+      cdiGribUseTimeRangeIndicator = 1;
+      switch ( timeRangeIND )
+          {
+              case 0:  tsteptype = TSTEP_INSTANT; break;
+              case 2:  tsteptype = TSTEP_INSTANT2;
+                       strcpy(stepType, "instant2");  // was incorrectly set before into accum
+                       break;
+              case 4:  tsteptype = TSTEP_ACCUM; break;
+              case 5:  tsteptype = TSTEP_DIFF; break;
+              default:
+                if ( lprint )
+                {
+                  if (CDI_Debug)
+                      Warning("timeRangeIND = %d;  stepType= %s; tsteptype=%d unsupported timeRangeIND at the moment, set to instant!", timeRangeIND, stepType, tsteptype);
+                  lprint = FALSE;
+                }
+                break;
+          }
+      if (CDI_Debug)
+          Warning("timeRangeIND = %d;  stepType= %s; tsteptype=%d", timeRangeIND, stepType, tsteptype);
+      }
+#endif // HIRLAM_EXTENSIONS
     }
 
   return tsteptype;
@@ -454,6 +498,11 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
   long editionNumber = gribEditionNumber(gh);
   int gridtype = gribapiGetGridType(gh);
   int projtype = (gridtype == GRID_PROJECTION && gribapiGetIsRotated(gh)) ? CDI_PROJ_RLL : CDI_UNDEFID;
+  if ( gridtype == GRID_LCC )
+    {
+      gridtype = GRID_PROJECTION;
+      projtype = CDI_PROJ_LCC;
+    }
   /*
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED )
     {
@@ -487,7 +536,7 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       if ( numberOfPoints != nlon*nlat )
         Error("numberOfPoints (%ld) and gridSize (%ld) differ!", numberOfPoints, nlon*nlat);
 
-      grid->size  = (int)numberOfPoints;
+      grid->size   = (int)numberOfPoints;
       grid->x.size = (int)nlon;
       grid->y.size = (int)nlat;
       grid->x.inc  = 0;
@@ -502,17 +551,19 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       if ( gridtype == GRID_LONLAT && nlat > 1 )
         FAIL_ON_GRIB_ERROR(grib_get_double, gh, "jDirectionIncrementInDegrees", &grid->y.inc);
 
+      long iscan, jscan;
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "iScansNegatively", &iscan);
+      FAIL_ON_GRIB_ERROR(grib_get_long, gh, "jScansPositively", &jscan);
+      if (  iscan ) grid->x.inc = - grid->x.inc;
+      if ( !jscan ) grid->y.inc = - grid->y.inc;
+
       if ( grid->x.inc < -999 || grid->x.inc > 999 ) grid->x.inc = 0;
       if ( grid->y.inc < -999 || grid->y.inc > 999 ) grid->y.inc = 0;
 
-      if ( grid->y.inc > 0 && grid->y.first > grid->y.last ) grid->y.inc = -grid->y.inc;
-
       /* if ( IS_NOT_EQUAL(grid->x.first, 0) || IS_NOT_EQUAL(grid->x.last, 0) ) */
       {
         if ( grid->x.size > 1 )
           {
-            if ( (grid->x.first >= grid->x.last) && (grid->x.first >= 180) ) grid->x.first -= 360;
-
             if ( editionNumber <= 1 )
               {
                 /* correct xinc if necessary */
@@ -605,13 +656,12 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
         grid->y.flag = 2;
       }
     }
-  else if ( gridtype == GRID_LCC )
+  else if ( projtype == CDI_PROJ_LCC )
     {
-      int nlon, nlat;
       FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Nx", &lpar);
-      nlon = (int)lpar;
+      int nlon = (int)lpar;
       FAIL_ON_GRIB_ERROR(grib_get_long, gh, "Ny", &lpar);
-      nlat = (int)lpar;
+      int nlat = (int)lpar;
 
       if ( numberOfPoints != nlon*nlat )
         Error("numberOfPoints (%d) and gridSize (%d) differ!", (int)numberOfPoints, nlon*nlat);
@@ -620,24 +670,18 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       grid->x.size = nlon;
       grid->y.size = nlat;
 
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &grid->lcc.xinc);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &grid->lcc.yinc);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "longitudeOfFirstGridPointInDegrees", &grid->lcc.originLon);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "latitudeOfFirstGridPointInDegrees", &grid->lcc.originLat);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "LoVInDegrees", &grid->lcc.lonParY);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin1InDegrees", &grid->lcc.lat1);
-      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "Latin2InDegrees", &grid->lcc.lat2);
-
-      if ( editionNumber <= 1 )
-        {
-          FAIL_ON_GRIB_ERROR(grib_get_long, gh, "projectionCenterFlag", &lpar);
-          grid->lcc.projflag  = (int) lpar;
-          FAIL_ON_GRIB_ERROR(grib_get_long, gh, "scanningMode", &lpar);
-          grid->lcc.scanflag  = (int) lpar;
-        }
-
-      grid->x.flag = 0;
-      grid->y.flag = 0;
+      double xinc, yinc;
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DxInMetres", &xinc);
+      FAIL_ON_GRIB_ERROR(grib_get_double, gh, "DyInMetres", &yinc);
+
+      grid->x.first = 0;
+      grid->x.last  = 0;
+      grid->x.inc   = xinc;
+      grid->y.first = 0;
+      grid->y.last  = 0;
+      grid->y.inc   = yinc;
+      grid->x.flag  = 2;
+      grid->y.flag  = 2;
     }
   else if ( gridtype == GRID_SPECTRAL )
     {
@@ -713,6 +757,47 @@ void gribapiGetGrid(grib_handle *gh, grid_t *grid)
       Error("Unsupported grid type: %s", gridNamePtr(gridtype));
     }
 
+  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_LONLAT || gridtype == GRID_PROJECTION )
+    {
+      long temp;
+      GRIB_CHECK(grib_get_long(gh, "uvRelativeToGrid", &temp), 0);
+      assert(temp == 0 || temp == 1);
+      grid->uvRelativeToGrid = (bool)temp;
+    }
+
+  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_LONLAT || gridtype == GRID_PROJECTION )
+    {
+      long temp;
+      GRIB_CHECK(grib_get_long(gh, "iScansNegatively", &temp), 0);
+      grid->iScansNegatively = (bool)temp;
+      GRIB_CHECK(grib_get_long(gh, "jScansPositively", &temp), 0);
+      grid->jScansPositively = (bool)temp;
+      GRIB_CHECK(grib_get_long(gh, "jPointsAreConsecutive", &temp), 0);
+      grid->jPointsAreConsecutive = (bool)temp;
+      grid->scanningMode = 128*grid->iScansNegatively + 64*grid->jScansPositively + 32*grid->jPointsAreConsecutive;
+      /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
+                   64  = 128 * 0                + 64 *        1         + 32 * 0
+                   00  = 128 * 0                + 64 *        0         + 32 * 0
+                   96  = 128 * 0                + 64 *        1         + 32 * 1
+         Default / implicit scanning mode is 64:
+                            i and j scan positively, i points are consecutive (row-major)        */
+#ifdef HIRLAM_EXTENSIONS
+      if (cdiDebugExt>=30)
+      {
+        //  indicatorOfParameter=33,indicatorOfTypeOfLevel=105,level
+        long paramId, levelTypeId, levelId;
+        GRIB_CHECK(grib_get_long(gh, "indicatorOfParameter", &paramId), 0);
+        GRIB_CHECK(grib_get_long(gh, "indicatorOfTypeOfLevel", &levelTypeId), 0);
+        GRIB_CHECK(grib_get_long(gh, "level", &levelId), 0);
+        Message("(param,ltype,level) = (%3d,%3d,%4d); Scanning mode = %02d -> bits:(%1d.%1d.%1d)*32;  uvRelativeToGrid = %02d",\
+                (int)paramId, (int)levelTypeId, (int)levelId,
+                grid->scanningMode,grid->jPointsAreConsecutive,
+                grid->jScansPositively,grid->iScansNegatively,
+                grid->uvRelativeToGrid);
+      }
+#endif //HIRLAM_EXTENSIONS
+    }
+
   grid->type  = gridtype;
   grid->projtype  = projtype;
 }
diff --git a/libcdi/src/gribapi_utilities.h b/libcdi/src/gribapi_utilities.h
index b9f2084..2495f83 100644
--- a/libcdi/src/gribapi_utilities.h
+++ b/libcdi/src/gribapi_utilities.h
@@ -33,6 +33,11 @@ int gribapiGetParam(grib_handle *gh);
 int gribapiGetGridType(grib_handle *gh);
 void gribapiGetGrid(grib_handle *gh, grid_t *grid);
 
+#ifdef HIRLAM_EXTENSIONS
+void gribapiSetDataTimeRangeIndicator(grib_handle *gh, int timeRangeIndicator);
+void gribapiGetDataTimeRangeIndicator(grib_handle *gh, int *timeRangeIndicator);
+#endif // #ifdef HIRLAM_EXTENSIONS
+
 #endif
 
 #endif
diff --git a/libcdi/src/grid.c b/libcdi/src/grid.c
index fb64c10..c2b77ec 100644
--- a/libcdi/src/grid.c
+++ b/libcdi/src/grid.c
@@ -20,6 +20,9 @@
 #include "serialize.h"
 #include "vlist.h"
 
+double grid_missval = -9999.;
+int (*proj_lonlat_to_lcc_func)() = NULL;
+int (*proj_lcc_to_lonlat_func)() = NULL;
 
 /* the value in the second pair of brackets must match the length of
  * the longest string (including terminating NUL) */
@@ -83,6 +86,29 @@ grid_t *grid_to_pointer(int gridID)
 
 #define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
 
+static
+bool cdiInqAttConvertedToFloat(int gridID, int atttype, const char *attname, int attlen, double *attflt)
+{
+  bool status = true;
+
+  if ( atttype == CDI_DATATYPE_INT32 )
+    {
+      int attint[attlen];
+      cdiInqAttInt(gridID, CDI_GLOBAL, attname, attlen, attint);
+      for ( int i = 0; i < attlen; ++i ) attflt[i] = (double)attint[i];
+    }
+  else if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
+    {
+      cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, attflt);
+    }
+  else
+    {
+      status = false;
+    }
+
+  return status;
+}
+
 
 void grid_init(grid_t *gridptr)
 {
@@ -107,17 +133,6 @@ void grid_init(grid_t *gridptr)
   gridptr->y.last        = 0.0;
   gridptr->y.inc         = 0.0;
 
-  gridptr->lcc.originLon = 0.0;
-  gridptr->lcc.originLat = 0.0;
-  gridptr->lcc.lonParY   = 0.0;
-  gridptr->lcc.lat1      = 0.0;
-  gridptr->lcc.lat2      = 0.0;
-  gridptr->lcc.xinc      = 0.0;
-  gridptr->lcc.yinc      = 0.0;
-  gridptr->lcc.projflag  = 0;
-  gridptr->lcc.scanflag  = 0;
-  gridptr->lcc.defined   = FALSE;
-
   gridptr->gme.nd        = 0;
   gridptr->gme.ni        = 0;
   gridptr->gme.ni2       = 0;
@@ -157,6 +172,17 @@ void grid_init(grid_t *gridptr)
   gridptr->vtable        = &cdiGridVtable;
   gridptr->atts.nalloc   = MAX_ATTRIBUTES;
   gridptr->atts.nelems   = 0;
+  gridptr->uvRelativeToGrid      = 0;   // Some models deliver wind U,V relative to the grid-cell
+  gridptr->iScansNegatively      = 0;
+  gridptr->jScansPositively      = 1;
+  gridptr->jPointsAreConsecutive = 0;
+  gridptr->scanningMode          = 128*gridptr->iScansNegatively + 64*gridptr->jScansPositively + 32*gridptr->jPointsAreConsecutive;
+  /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
+               64  = 128 * 0                + 64 *        1         + 32 * 0
+               00  = 128 * 0                + 64 *        0         + 32 * 0
+               96  = 128 * 0                + 64 *        1         + 32 * 1
+     Default / implicit scanning mode is 64:
+                        i and j scan positively, i points are consecutive (row-major)        */
 }
 
 
@@ -455,7 +481,7 @@ void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double y
 @Parameter
     @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
                      The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
-                     @func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL},
+                     @func{GRID_LONLAT}, @func{GRID_PROJECTION}, @func{GRID_SPECTRAL},
                      @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
     @Item  size      Number of gridpoints.
 
@@ -998,6 +1024,13 @@ void gridVerifyProj(int gridID)
       gridSetName(gridptr->x.units, "degrees");
       gridSetName(gridptr->y.units, "degrees");
     }
+  else if ( projtype == CDI_PROJ_LCC )
+    {
+      gridptr->x.stdname = xystdname_tab[grid_xystdname_projection][0];
+      gridptr->y.stdname = xystdname_tab[grid_xystdname_projection][1];
+      gridSetName(gridptr->x.units, "m");
+      gridSetName(gridptr->y.units, "m");
+    }
 }
 
 /*
@@ -1015,7 +1048,7 @@ The function @func{gridInqType} returns the type of a Grid.
 @func{gridInqType} returns the type of the grid,
 one of the set of predefined CDI grid types.
 The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
- at func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL}, @func{GRID_GME},
+ at func{GRID_LONLAT}, @func{GRID_PROJECTION}, @func{GRID_SPECTRAL}, @func{GRID_GME},
 @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
 
 @EndFunction
@@ -1794,13 +1827,11 @@ void gridInqParamRLL(int gridID, double *xpole, double *ypole, double *angle)
       for ( int iatt = 0; iatt < natts; ++iatt )
         {
           cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
-
           if ( attlen != 1 ) continue;
 
-          if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
+          double attflt;
+          if ( cdiInqAttConvertedToFloat(gridID, atttype, attname, attlen, &attflt) )
             {
-              double attflt;
-              cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, &attflt);
               if      ( strcmp(attname, "grid_north_pole_longitude") == 0 ) *xpole = attflt;
               else if ( strcmp(attname, "grid_north_pole_latitude")  == 0 ) *ypole = attflt;
               else if ( strcmp(attname, "north_pole_grid_longitude") == 0 ) *angle = attflt;
@@ -1827,7 +1858,7 @@ void gridDefParamRLL(int gridID, double xpole, double ypole, double angle)
 
   const char *mapping = "rotated_latitude_longitude";
   cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapping);
-  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", strlen(mapping), mapping);
+  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", (int)(strlen(mapping)), mapping);
   cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_longitude", CDI_DATATYPE_FLT64, 1, &xpole);
   cdiDefAttFlt(gridID, CDI_GLOBAL, "grid_north_pole_latitude", CDI_DATATYPE_FLT64, 1, &ypole);
   if ( IS_NOT_EQUAL(angle, 0) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "north_pole_grid_longitude", CDI_DATATYPE_FLT64, 1, &angle);
@@ -1909,11 +1940,12 @@ void gridChangeType(int gridID, int gridtype)
 static
 void grid_check_cyclic(grid_t *gridptr)
 {
-  gridptr->isCyclic = FALSE;
+  gridptr->isCyclic = 0;
   enum { numVertices = 4 };
   size_t xsize = gridptr->x.size >= 0 ? (size_t)gridptr->x.size : 0,
-    ysize = gridptr->y.size >= 0 ? (size_t)gridptr->y.size : 0;
+         ysize = gridptr->y.size >= 0 ? (size_t)gridptr->y.size : 0;
   const double *xvals = gridptr->vtable->inqXValsPtr(gridptr),
+               *yvals = gridptr->vtable->inqYValsPtr(gridptr),
     (*xbounds)[numVertices]
     = (const double (*)[numVertices])gridptr->vtable->inqXBoundsPtr(gridptr);
 
@@ -1928,23 +1960,31 @@ void grid_check_cyclic(grid_t *gridptr)
           double x0 = 2*xvals[xsize-1]-xvals[xsize-2]-360;
 
           if ( IS_NOT_EQUAL(xvals[0], xvals[xsize-1]) )
-            if ( fabs(x0 - xvals[0]) < 0.01*xinc ) gridptr->isCyclic = TRUE;
+            if ( fabs(x0 - xvals[0]) < 0.01*xinc ) gridptr->isCyclic = 1;
         }
     }
   else if ( gridptr->type == GRID_CURVILINEAR )
     {
-      if ( xvals && xsize > 1 )
+      bool lcheck = true;
+      if ( yvals && xvals )
+        {
+          if ( (fabs(yvals[0] - yvals[xsize-1]) > fabs(yvals[0] - yvals[xsize*ysize-xsize])) &&
+               (fabs(yvals[xsize*ysize-xsize] - yvals[xsize*ysize-1]) > fabs(yvals[xsize-1] - yvals[xsize*ysize-1])) )
+            lcheck = false;
+        }
+      else lcheck = false;
+
+      if ( lcheck && xvals && xsize > 1 )
         {
           size_t nc = 0;
           for ( size_t j = 0; j < ysize; ++j )
             {
               size_t i1 = j*xsize,
-                i2 = j*xsize+1,
-                in = j*xsize+(xsize-1);
+                     i2 = j*xsize+1,
+                     in = j*xsize+(xsize-1);
               double val1 = xvals[i1],
-                val2 = xvals[i2],
-                valn = xvals[in];
-
+                     val2 = xvals[i2],
+                     valn = xvals[in];
               double xinc = fabs(val2-val1);
 
 	      if ( val1 <    1 && valn > 300 ) val1 += 360;
@@ -1957,16 +1997,16 @@ void grid_check_cyclic(grid_t *gridptr)
 
               nc += fabs(x0-val1) < 0.5*xinc;
             }
-          gridptr->isCyclic = nc > ysize/2 ? TRUE : FALSE;
+          gridptr->isCyclic = nc > ysize/2;
         }
 
-      if ( xbounds && xsize > 1 )
+      if ( lcheck && xbounds && xsize > 1 )
 	{
           bool isCyclic = true;
 	  for ( size_t j = 0; j < ysize; ++j )
 	    {
 	      size_t i1 = j*xsize,
-                i2 = j*xsize+(xsize-1);
+                     i2 = j*xsize+(xsize-1);
 	      for (size_t k1 = 0; k1 < numVertices; ++k1 )
 		{
 		  double val1 = xbounds[i1][k1];
@@ -1990,7 +2030,7 @@ void grid_check_cyclic(grid_t *gridptr)
               foundCloseVertices:
               ;
 	    }
-          gridptr->isCyclic = (int) isCyclic;
+          gridptr->isCyclic = isCyclic;
 	}
     }
 }
@@ -2217,6 +2257,16 @@ bool gridCompare(int gridID, const grid_t *grid, bool coord_compare)
 	}
     }
 
+  if ( (grid->scanningMode != gridInqScanningMode(gridID)) || (grid->uvRelativeToGrid != gridInqUvRelativeToGrid(gridID)) )
+    {
+      // often grid definition may differ in UV-relativeToGrid
+      differ = 1;
+#ifdef HIRLAM_EXTENSIONS
+      if ( cdiDebugExt>=200 )
+        printf("gridCompare(gridID=%d): Differs: grid.scanningMode [%d] != gridInqScanningMode(gridID) [%d] or  grid.uvRelativeToGrid [%ld] != gridInqUvRelativeToGrid(gridID) [%d]\n",
+               gridID, grid->scanningMode, gridInqScanningMode(gridID), grid->uvRelativeToGrid, gridInqUvRelativeToGrid(gridID) );
+#endif // HIRLAM_EXTENSIONS
+    }
   return differ;
 }
 
@@ -2244,9 +2294,6 @@ int gridCompareP(void *gridptr1, void *gridptr2)
 
   if ( g1->type          != g2->type         ) return differ;
   if ( g1->prec          != g2->prec         ) return differ;
-  if ( g1->lcc.projflag  != g2->lcc.projflag ) return differ;
-  if ( g1->lcc.scanflag  != g2->lcc.scanflag ) return differ;
-  if ( g1->lcc.defined   != g2->lcc.defined  ) return differ;
   if ( g1->isCyclic      != g2->isCyclic     ) return differ;
   if ( g1->x.flag        != g2->x.flag       ) return differ;
   if ( g1->y.flag        != g2->y.flag       ) return differ;
@@ -2270,13 +2317,8 @@ int gridCompareP(void *gridptr1, void *gridptr2)
   if ( IS_NOT_EQUAL(g1->y.last        , g2->y.last)        ) return differ;
   if ( IS_NOT_EQUAL(g1->x.inc	      , g2->x.inc)         ) return differ;
   if ( IS_NOT_EQUAL(g1->y.inc	      , g2->y.inc)         ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.originLon , g2->lcc.originLon) ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.originLat , g2->lcc.originLat) ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.lonParY   , g2->lcc.lonParY)   ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.lat1      , g2->lcc.lat1)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.lat2      , g2->lcc.lat2)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.xinc      , g2->lcc.xinc)      ) return differ;
-  if ( IS_NOT_EQUAL(g1->lcc.yinc      , g2->lcc.yinc)      ) return differ;
+  if ( IS_NOT_EQUAL(g1->uvRelativeToGrid     , g2->uvRelativeToGrid)     ) return differ;
+  if ( IS_NOT_EQUAL(g1->scanningMode         , g2->scanningMode)         ) return differ;
 
   const double *restrict g1_xvals = g1->vtable->inqXValsPtr(g1),
                *restrict g2_xvals = g2->vtable->inqXValsPtr(g2);
@@ -2425,7 +2467,6 @@ void gridComplete(grid_t *grid)
     case GRID_UNSTRUCTURED:
     case GRID_CURVILINEAR:
     case GRID_GENERIC:
-    case GRID_LCC:
     case GRID_PROJECTION:
       {
 	if ( grid->x.size > 0 ) gridDefXsize(gridID, grid->x.size);
@@ -2442,9 +2483,7 @@ void gridComplete(grid_t *grid)
 	    double *xvals = (double *) Malloc((size_t)grid->x.size * sizeof (double));
 	    gridGenXvals(grid->x.size, grid->x.first, grid->x.last, grid->x.inc, xvals);
 	    grid->x.vals = xvals;
-	    /*
-	    gridDefXinc(gridID, grid->x.inc);
-	    */
+	    // gridDefXinc(gridID, grid->x.inc);
 	  }
 
 	if ( grid->y.flag == 2 )
@@ -2453,9 +2492,7 @@ void gridComplete(grid_t *grid)
 	    double *yvals = (double *) Malloc((size_t)grid->y.size * sizeof (double));
 	    gridGenYvals(gridtype, grid->y.size, grid->y.first, grid->y.last, grid->y.inc, yvals);
 	    grid->y.vals = yvals;
-	    /*
-	    gridDefYinc(gridID, grid->y.inc);
-	    */
+	    // gridDefYinc(gridID, grid->y.inc);
 	  }
 
 	if ( grid->projtype == CDI_PROJ_RLL )
@@ -2470,22 +2507,13 @@ void gridComplete(grid_t *grid)
 	    if ( grid->y.units[0] == 0 ) strcpy(grid->y.units, "degrees");
 	  }
 
-        switch (gridtype)
+        if ( gridtype == GRID_UNSTRUCTURED )
           {
-          case GRID_LCC:
-            gridDefParamLCC(gridID, grid->lcc.originLon, grid->lcc.originLat, grid->lcc.lonParY,
-                       grid->lcc.lat1, grid->lcc.lat2, grid->lcc.xinc, grid->lcc.yinc,
-                       grid->lcc.projflag, grid->lcc.scanflag);
-            break;
-          case GRID_UNSTRUCTURED:
-            {
-              int number = grid->number;
-              int position = grid->position >= 0 ? grid->position : 0;
-              if ( number > 0 ) gridDefNumber(gridID, number);
-              gridDefPosition(gridID, position);
-            }
-            break;
-	  }
+            int number = grid->number;
+            int position = grid->position >= 0 ? grid->position : 0;
+            if ( number > 0 ) gridDefNumber(gridID, number);
+            gridDefPosition(gridID, position);
+          }
 
 	break;
       }
@@ -2579,7 +2607,7 @@ int gridGenerate(const grid_t *grid)
   int valdef_group1 = 0;
   static const int valdef_group1_tab[] = {
     GRID_LONLAT, GRID_GAUSSIAN, GRID_UNSTRUCTURED, GRID_CURVILINEAR,
-    GRID_GENERIC, GRID_LCC, GRID_PROJECTION
+    GRID_GENERIC, GRID_PROJECTION
   };
   for ( size_t i = 0; i < sizeof (valdef_group1_tab) / sizeof (valdef_group1_tab[0]); ++i)
     valdef_group1 |= (gridtype == valdef_group1_tab[i]);
@@ -2604,17 +2632,13 @@ int gridGenerate(const grid_t *grid)
   gridptr->y.inc = grid->y.inc;
   if ( valdef_group1 && grid->area)
     gridDefArea(gridID, grid->area);
-  gridptr->lcc.originLon = grid->lcc.originLon;
-  gridptr->lcc.originLat = grid->lcc.originLat;
-  gridptr->lcc.lonParY = grid->lcc.lonParY;
-  gridptr->lcc.lat1 = grid->lcc.lat1;
-  gridptr->lcc.lat2 = grid->lcc.lat2;
-  gridptr->lcc.xinc = grid->lcc.xinc;
-  gridptr->lcc.yinc = grid->lcc.yinc;
-  gridptr->lcc.projflag = grid->lcc.projflag;
-  gridptr->lcc.scanflag = grid->lcc.scanflag;
   gridptr->number = grid->number;
   gridptr->position = grid->position;
+  gridptr->uvRelativeToGrid       = grid->uvRelativeToGrid;
+  gridptr->scanningMode           = grid->scanningMode;
+  gridptr->iScansNegatively       = grid->iScansNegatively;
+  gridptr->jScansPositively       = grid->jScansPositively;
+  gridptr->jPointsAreConsecutive  = grid->jPointsAreConsecutive;
   memcpy(gridptr->uuid, grid->uuid, CDI_UUID_SIZE);
   if ( gridtype == GRID_UNSTRUCTURED && grid->reference )
     gridDefReference(gridID, grid->reference);
@@ -3239,7 +3263,7 @@ void gridPrintAttributes(FILE *fp, int gridID)
 static
 void gridPrintKernel(int gridID, int opt, FILE *fp)
 {
-  int xdim, ydim;
+  size_t xdimLen, ydimLen;
   char attstr[CDI_MAX_NAME];
   char attstr2[CDI_MAX_NAME];
   unsigned char uuidOfHGrid[CDI_UUID_SIZE];
@@ -3313,18 +3337,18 @@ void gridPrintKernel(int gridID, int opt, FILE *fp)
 
 	if ( type == GRID_CURVILINEAR || type == GRID_UNSTRUCTURED )
 	  {
-	    xdim = gridsize;
-	    ydim = gridsize;
+	    xdimLen = (size_t)gridsize;
+	    ydimLen = (size_t)gridsize;
 	  }
         else if ( type == GRID_GAUSSIAN_REDUCED )
           {
-	    xdim = 2;
-	    ydim = ysize;
+	    xdimLen = 2;
+	    ydimLen = (size_t)ysize;
           }
 	else
 	  {
-	    xdim = xsize;
-	    ydim = ysize;
+	    xdimLen = (size_t)xsize;
+	    ydimLen = (size_t)ysize;
 	  }
 
 	if ( type == GRID_UNSTRUCTURED )
@@ -3383,7 +3407,7 @@ void gridPrintKernel(int gridID, int opt, FILE *fp)
             double *xbounds = (double*) Malloc(nxbounds*sizeof(double));
             gridInqXbounds(gridID, xbounds);
             static const char prefix[] = "xbounds   = ";
-            printBounds(fp, dig, prefix, sizeof(prefix)-1, xdim, nvertex, xbounds);
+            printBounds(fp, dig, prefix, sizeof(prefix)-1, xdimLen, (size_t)nvertex, xbounds);
             Free(xbounds);
 	  }
 
@@ -3418,16 +3442,16 @@ void gridPrintKernel(int gridID, int opt, FILE *fp)
             double *ybounds = (double*) Malloc(nybounds*sizeof(double));
             gridInqYbounds(gridID, ybounds);
             static const char prefix[] = "ybounds   = ";
-            printBounds(fp, dig, prefix, sizeof(prefix)-1, ydim, nvertex, ybounds);
+            printBounds(fp, dig, prefix, sizeof(prefix)-1, ydimLen, (size_t)nvertex, ybounds);
             Free(ybounds);
 	  }
 
 	if ( gridHasArea(gridID) )
 	  {
-            double *area = (double*) Malloc(gridsize*sizeof(double));
+            double *area = (double*) Malloc((size_t)gridsize*sizeof(double));
             gridInqArea(gridID, area);
             static const char prefix[] = "area      = ";
-            printDblsPrefixAutoBrk(fp, dig, prefix, sizeof(prefix)-1, gridsize, area);
+            printDblsPrefixAutoBrk(fp, dig, prefix, sizeof(prefix)-1, (size_t)gridsize, area);
             Free(area);
 	  }
 
@@ -3445,27 +3469,6 @@ void gridPrintKernel(int gridID, int opt, FILE *fp)
 
 	break;
       }
-    case GRID_LCC:
-      {
-	double originLon = 0, originLat = 0, lonParY = 0, lat1 = 0, lat2 = 0, xincm = 0, yincm = 0;
-	int projflag = 0, scanflag = 0;
-	gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                        &projflag, &scanflag);
-
-	fprintf(fp,
-                "originLon = %.*g\n"
-                "originLat = %.*g\n"
-                "lonParY   = %.*g\n"
-                "lat1      = %.*g\n"
-                "lat2      = %.*g\n"
-                "xinc      = %.*g\n"
-                "yinc      = %.*g\n"
-                "projection = %s\n",
-                dig, originLon, dig, originLat, dig, lonParY,
-                dig, lat1, dig, lat2, dig, xincm, dig, yincm,
-                (projflag & 128) == 0 ? "northpole" : "southpole");
-	break;
-      }
     case GRID_SPECTRAL:
       {
         fprintf(fp, "truncation = %d\n"
@@ -3589,97 +3592,156 @@ const double *gridInqYvalsPtr(int gridID)
 @Function  gridDefParamLCC
 @Title     Define the parameter of a Lambert Conformal Conic grid
 
- at Prototype void gridDefParamLCC(int gridID, double originLon, double originLat, double lonParY, double lat1, double lat2, double xinc, double yinc, int projflag, int scanflag)
+ at Prototype void gridDefParamLCC(int gridID, double missval, double lon_0, double lat_0, double lat_1, double lat_2, double a, double rf, double xval_0, double yval_0, double x_0, double y_0)
 @Parameter
     @Item  gridID    Grid ID, from a previous call to @fref{gridCreate}.
-    @Item  originLon Longitude of the first grid point.
-    @Item  originLat Latitude of the first grid point.
-    @Item  lonParY   The East longitude of the meridian which is parallel to the Y-axis.
-    @Item  lat1      First latitude from the pole at which the secant cone cuts the sphere.
-    @Item  lat2      Second latitude at which the secant cone cuts the sphere.
-    @Item  xinc      X-direction grid lenght in meter.
-    @Item  yinc      Y-direction grid lenght in meter.
-    @Item  projflag  Projection centre flag.
-    @Item  scanflag  Scanning mode flag.
+    @Item  missval   Missing value
+    @Item  lon_0     The East longitude of the meridian which is parallel to the Y-axis.
+    @Item  lat_0     Latitude of the projection origin
+    @Item  lat_1     First latitude from the pole at which the secant cone cuts the sphere.
+    @Item  lat_2     Second latitude at which the secant cone cuts the sphere.
+    @Item  a         Earth radius in metres (optional).
+    @Item  rf        Inverse flattening (1/f) (optional).
+    @Item  xval_0    Longitude of the first grid point in degree (optional).
+    @Item  yval_0    Latitude of the first grid point in degree (optional).
+    @Item  x_0       False easting (optional).
+    @Item  y_0       False northing (optional).
 
 @Description
 The function @func{gridDefParamLCC} defines the parameter of a Lambert Conformal Conic grid.
 
 @EndFunction
 */
-void gridDefParamLCC(int gridID, double originLon, double originLat, double lonParY,
-                double lat1, double lat2, double xinc, double yinc,
-                int projflag, int scanflag)
-{
+void gridDefParamLCC(int gridID, double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                     double a, double rf, double xval_0, double yval_0, double x_0, double y_0)
+{
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, "Lambert_Conformal");
+
+  const char *mapname = "lambert_conformal_conic";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapname);
+  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", strlen(mapname), mapname);
+  int nlats = 0;
+  double lats[2];
+  lats[nlats++] = lat_1;
+  if ( IS_NOT_EQUAL(lat_1, lat_2) ) lats[nlats++] = lat_2;
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "standard_parallel", CDI_DATATYPE_FLT64, nlats, lats);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "longitude_of_central_meridian", CDI_DATATYPE_FLT64, 1, &lon_0);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "latitude_of_projection_origin", CDI_DATATYPE_FLT64, 1, &lat_2);
+  if ( a > 0 ) cdiDefAttFlt(gridID, CDI_GLOBAL, "earth_radius", CDI_DATATYPE_FLT64, 1, &a);
+  if ( rf > 0 ) cdiDefAttFlt(gridID, CDI_GLOBAL, "inverse_flattening", CDI_DATATYPE_FLT64, 1, &rf);
+  if ( IS_NOT_EQUAL(x_0, missval) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "false_easting", CDI_DATATYPE_FLT64, 1, &x_0);
+  if ( IS_NOT_EQUAL(y_0, missval) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "false_northing", CDI_DATATYPE_FLT64, 1, &y_0);
+  if ( IS_NOT_EQUAL(xval_0, missval) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "longitudeOfFirstGridPointInDegrees", CDI_DATATYPE_FLT64, 1, &xval_0);
+  if ( IS_NOT_EQUAL(yval_0, missval) ) cdiDefAttFlt(gridID, CDI_GLOBAL, "latitudeOfFirstGridPointInDegrees", CDI_DATATYPE_FLT64, 1, &yval_0);
+
   grid_t *gridptr = grid_to_pointer(gridID);
+  gridptr->projtype = CDI_PROJ_LCC;
 
-  if ( gridptr->type != GRID_LCC )
-    Warning("Definition of LCC grid for %s grid not allowed!",
-	    gridNamePtr(gridptr->type));
-  else
-    {
-      gridptr->lcc.originLon = originLon;
-      gridptr->lcc.originLat = originLat;
-      gridptr->lcc.lonParY   = lonParY;
-      gridptr->lcc.lat1      = lat1;
-      gridptr->lcc.lat2      = lat2;
-      gridptr->lcc.xinc      = xinc;
-      gridptr->lcc.yinc      = yinc;
-      gridptr->lcc.projflag  = projflag;
-      gridptr->lcc.scanflag  = scanflag;
-      gridptr->lcc.defined   = TRUE;
-      gridMark4Update(gridID);
-    }
+  gridVerifyProj(gridID);
 }
 
 /*
 @Function  gridInqParamLCC
 @Title     Get the parameter of a Lambert Conformal Conic grid
 
- at Prototype void gridInqParamLCC(int gridID, double *originLon, double *originLat, double *lonParY, double *lat1, double *lat2, double *xinc, double *yinc, int *projflag, int *scanflag)
+ at Prototype void gridInqParamLCC(int gridID, double missval, double *lon_0, double *lat_0, double *lat_1, double *lat_2, double *a, double *rf, double *xval_0, double *yval_0, double *x_0, double *y_0)
 @Parameter
     @Item  gridID    Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
-    @Item  originLon Longitude of the first grid point.
-    @Item  originLat Latitude of the first grid point.
-    @Item  lonParY   The East longitude of the meridian which is parallel to the Y-axis.
-    @Item  lat1      First latitude from the pole at which the secant cone cuts the sphere.
-    @Item  lat2      Second latitude at which the secant cone cuts the sphere.
-    @Item  xinc      X-direction grid lenght in meter.
-    @Item  yinc      Y-direction grid lenght in meter.
-    @Item  projflag  Projection centre flag.
-    @Item  scanflag  Scanning mode flag.
- 
+    @Item  missval   Missing value
+    @Item  lon_0     The East longitude of the meridian which is parallel to the Y-axis.
+    @Item  lat_0     Latitude of the projection origin
+    @Item  lat_1     First latitude from the pole at which the secant cone cuts the sphere.
+    @Item  lat_2     Second latitude at which the secant cone cuts the sphere.
+    @Item  a         Earth radius in metres (optional).
+    @Item  rf        Inverse flattening (1/f) (optional).
+    @Item  xval_0    Longitude of the first grid point in degree (optional).
+    @Item  yval_0    Latitude of the first grid point in degree (optional).
+    @Item  x_0       False easting (optional).
+    @Item  y_0       False northing (optional).
+
 @Description
 The function @func{gridInqParamLCC} returns the parameter of a Lambert Conformal Conic grid.
 
 @EndFunction
 */
-void gridInqParamLCC(int gridID, double *originLon, double *originLat, double *lonParY,
-                double *lat1, double *lat2, double *xinc, double *yinc,
-                int *projflag, int *scanflag)
+int gridInqParamLCC(int gridID, double missval, double *lon_0, double *lat_0, double *lat_1, double *lat_2,
+                    double *a, double *rf, double *xval_0, double *yval_0, double *x_0, double *y_0)
 {
-  grid_t *gridptr = grid_to_pointer(gridID);
+  *a = 0; *rf = 0;
+  *lon_0 = missval; *lat_0 = missval, *lat_1 = missval, *lat_2 = missval;
+  *xval_0 = missval; *yval_0 = missval; *x_0 = missval, *y_0 = missval;
 
-  if ( gridptr->type != GRID_LCC )
-    Warning("Inquire of LCC grid definition for %s grid not allowed!",
-	    gridNamePtr(gridptr->type));
-  else
+  int status = -1;
+  if ( gridInqType(gridID) != GRID_PROJECTION ) return status;
+
+  status = -2;
+  const char *projection = "lambert_conformal_conic";
+  char mapname[CDI_MAX_NAME]; mapname[0] = 0;
+  cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapname);
+  if ( mapname[0] && strcmp(mapname, projection) == 0 )
+    {
+      int atttype, attlen;
+      char attname[CDI_MAX_NAME+1];
+
+      int natts;
+      cdiInqNatts(gridID, CDI_GLOBAL, &natts);
+
+      if ( natts ) status = 0;
+
+      for ( int iatt = 0; iatt < natts; ++iatt )
+        {
+          cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
+          if ( attlen > 2 ) continue;
+
+          double attflt[2];
+          if ( cdiInqAttConvertedToFloat(gridID, atttype, attname, attlen, attflt) )
+            {
+              if      ( strcmp(attname, "earth_radius") == 0 )                       *a      = attflt[0];
+              else if ( strcmp(attname, "inverse_flattening") == 0 )                 *rf     = attflt[0];
+              else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )      *lon_0  = attflt[0];
+              else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )      *lat_0  = attflt[0];
+              else if ( strcmp(attname, "false_easting")  == 0 )                     *x_0    = attflt[0];
+              else if ( strcmp(attname, "false_northing") == 0 )                     *y_0    = attflt[0];
+              else if ( strcmp(attname, "longitudeOfFirstGridPointInDegrees") == 0 ) *xval_0 = attflt[0];
+              else if ( strcmp(attname, "latitudeOfFirstGridPointInDegrees")  == 0 ) *yval_0 = attflt[0];
+              else if ( strcmp(attname, "standard_parallel") == 0 )
+                {
+                  *lat_1 = attflt[0];
+                  *lat_2 = (attlen == 2) ? attflt[1] : attflt[0];
+                }
+            }
+        }
+    }
+
+  return status;
+}
+
+
+int gridVerifyGribParamLCC(int gridID, double missval, double *lon_0, double *lat_0, double *lat_1, double *lat_2,
+                           double *a, double *rf, double *xval_0, double *yval_0, double *x_0, double *y_0)
+{
+  static bool lwarn = true;
+
+  if ( lwarn )
     {
-      if ( gridptr->lcc.defined )
+      // lwarn = false;
+      const char *projection = "lambert_conformal_conic";
+      if ( IS_EQUAL(*lon_0, missval) ) { Warning("%s mapping parameter %s missing!", projection, "longitude_of_central_meridian"); }
+      if ( IS_EQUAL(*lat_0, missval) ) { Warning("%s mapping parameter %s missing!", projection, "latitude_of_central_meridian"); }
+      if ( IS_EQUAL(*lat_1, missval) ) { Warning("%s mapping parameter %s missing!", projection, "standard_parallel"); }
+      if ( IS_NOT_EQUAL(*x_0, missval) && IS_NOT_EQUAL(*y_0, grid_missval) && (IS_EQUAL(*xval_0, missval) || IS_EQUAL(*yval_0, missval)) )
         {
-          *originLon = gridptr->lcc.originLon;
-          *originLat = gridptr->lcc.originLat;
-          *lonParY   = gridptr->lcc.lonParY;
-          *lat1      = gridptr->lcc.lat1;
-          *lat2      = gridptr->lcc.lat2;
-          *xinc      = gridptr->lcc.xinc;
-          *yinc      = gridptr->lcc.yinc;
-          *projflag  = gridptr->lcc.projflag;
-          *scanflag  = gridptr->lcc.scanflag;
+          if ( proj_lcc_to_lonlat_func )
+            {
+              *xval_0 = -(*x_0); *yval_0 = -(*y_0);
+              proj_lcc_to_lonlat_func(missval, *lon_0, *lat_0, *lat_1, *lat_2, *a, *rf, 0.0, 0.0, (size_t)1, xval_0, yval_0);
+            }
+          if ( IS_EQUAL(*xval_0, missval) || IS_EQUAL(*yval_0, missval) )
+            Warning("%s mapping parameter %s missing!", projection, "longitudeOfFirstGridPointInDegrees and latitudeOfFirstGridPointInDegrees");
         }
-      else
-	Warning("Lambert Conformal grid undefined (gridID = %d)", gridID);
     }
+
+  return 0;
 }
 
 
@@ -3926,6 +3988,50 @@ void gridInqUUID(int gridID, unsigned char uuid[CDI_UUID_SIZE])
 }
 
 
+void gridDefUvRelativeToGrid(int gridID, int uvRelativeToGrid)
+{
+  grid_t *gridptr = grid_to_pointer(gridID);
+
+  if ( gridptr->uvRelativeToGrid != uvRelativeToGrid )
+    {
+      gridMark4Update(gridID);
+      gridptr->uvRelativeToGrid = (bool)uvRelativeToGrid;
+    }
+}
+
+
+int gridInqUvRelativeToGrid(int gridID)
+{
+  grid_t *gridptr = grid_to_pointer(gridID);
+  return gridptr->uvRelativeToGrid;
+}
+
+
+void gridDefScanningMode(int gridID, int mode)
+{
+  grid_t *gridptr = grid_to_pointer(gridID);
+
+  if ( gridptr->scanningMode != mode )
+    {
+      gridMark4Update(gridID);
+      gridptr->scanningMode = mode;
+    }
+}
+
+
+int gridInqScanningMode(int gridID)
+{
+  grid_t *gridptr = grid_to_pointer(gridID);
+
+  int scanningModeTMP  = 128 * gridptr->iScansNegatively + 64 * gridptr->jScansPositively + 32 * gridptr->jPointsAreConsecutive;
+  if ( scanningModeTMP != gridptr->scanningMode )
+    Message("WARNING: scanningMode (%d) ! = (%d) 128 * iScansNegatively(%d) + 64 * jScansPositively(%d) + 32 * jPointsAreConsecutive(%d) ",
+            gridptr->scanningMode, scanningModeTMP, gridptr->iScansNegatively,gridptr->jScansPositively,gridptr->jPointsAreConsecutive );
+
+  return gridptr->scanningMode;
+}
+
+
 void cdiGridGetIndexList(unsigned ngrids, int * gridIndexList)
 {
   reshGetResHListOfType(ngrids, gridIndexList, &gridOps);
@@ -3938,8 +4044,48 @@ gridTxCode ()
   return GRID;
 }
 
-enum { gridNint    = 28,
-       gridNdouble = 24,
+enum {
+  GRID_PACK_INT_IDX_SELF,
+  GRID_PACK_INT_IDX_TYPE,
+  GRID_PACK_INT_IDX_PREC,
+  GRID_PACK_INT_IDX_IS_CYCLIC,
+  GRID_PACK_INT_IDX_X_FLAG,
+  GRID_PACK_INT_IDX_Y_FLAG,
+  GRID_PACK_INT_IDX_GME_ND,
+  GRID_PACK_INT_IDX_GME_NI,
+  GRID_PACK_INT_IDX_GME_NI2,
+  GRID_PACK_INT_IDX_GME_NI3,
+  GRID_PACK_INT_IDX_NUMBER,
+  GRID_PACK_INT_IDX_POSITION,
+  GRID_PACK_INT_IDX_TRUNC,
+  GRID_PACK_INT_IDX_NVERTEX,
+  GRID_PACK_INT_IDX_NROWLON,
+  GRID_PACK_INT_IDX_SIZE,
+  GRID_PACK_INT_IDX_X_SIZE,
+  GRID_PACK_INT_IDX_Y_SIZE,
+  GRID_PACK_INT_IDX_LCOMPLEX,
+  GRID_PACK_INT_IDX_MEMBERMASK,
+  GRID_PACK_INT_IDX_XTSTDNNAME,
+  GRID_PACK_INT_IDX_YTSTDNNAME,
+  GRID_PACK_INT_IDX_UVRELATIVETOGRID,
+  GRID_PACK_INT_IDX_ISCANSNEGATIVELY,
+  GRID_PACK_INT_IDX_JSCANSPOSITIVELY,
+  GRID_PACK_INT_IDX_JPOINTSARECONSECUTIVE,
+  GRID_PACK_INT_IDX_SCANNINGMODE,
+  gridNint
+};
+
+enum {
+  GRID_PACK_DBL_IDX_X_FIRST,
+  GRID_PACK_DBL_IDX_Y_FIRST,
+  GRID_PACK_DBL_IDX_X_LAST,
+  GRID_PACK_DBL_IDX_Y_LAST,
+  GRID_PACK_DBL_IDX_X_INC,
+  GRID_PACK_DBL_IDX_Y_INC,
+  gridNdouble
+};
+
+enum {
        gridHasMaskFlag = 1 << 0,
        gridHasGMEMaskFlag = 1 << 1,
        gridHasXValsFlag = 1 << 2,
@@ -4106,30 +4252,34 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
 
     xassert(!force_id || targetID == gridP->self);
 
-    gridP->type          =   intBuffer[1];
-    gridP->prec          =   intBuffer[2];
-    gridP->lcc.projflag  =   intBuffer[3];
-    gridP->lcc.scanflag  =   intBuffer[4];
-    gridP->lcc.defined   =   (short)intBuffer[5];
-    gridP->isCyclic      =   (short)intBuffer[8];
-    gridP->x.flag        =   (short)intBuffer[10];
-    gridP->y.flag        =   (short)intBuffer[11];
-    gridP->gme.nd        =   intBuffer[12];
-    gridP->gme.ni        =   intBuffer[13];
-    gridP->gme.ni2       =   intBuffer[14];
-    gridP->gme.ni3       =   intBuffer[15];
-    gridP->number        =   intBuffer[16];
-    gridP->position      =   intBuffer[17];
-    gridP->trunc         =   intBuffer[18];
-    gridP->nvertex       =   intBuffer[19];
-    gridP->nrowlon       =   intBuffer[20];
-    gridP->size          =   intBuffer[21];
-    gridP->x.size        =   intBuffer[22];
-    gridP->y.size        =   intBuffer[23];
-    gridP->lcomplex      =   (bool)intBuffer[24];
-    memberMask           =   intBuffer[25];
-    gridP->x.stdname     =   xystdname_tab[intBuffer[26]][0];
-    gridP->y.stdname     =   xystdname_tab[intBuffer[27]][1];
+    gridP->type          =   intBuffer[GRID_PACK_INT_IDX_TYPE];
+    gridP->prec          =   intBuffer[GRID_PACK_INT_IDX_PREC];
+    gridP->isCyclic      =   (signed char)intBuffer[GRID_PACK_INT_IDX_IS_CYCLIC];
+    gridP->x.flag        =   (short)intBuffer[GRID_PACK_INT_IDX_X_FLAG];
+    gridP->y.flag        =   (short)intBuffer[GRID_PACK_INT_IDX_Y_FLAG];
+    gridP->gme.nd        =   intBuffer[GRID_PACK_INT_IDX_GME_ND];
+    gridP->gme.ni        =   intBuffer[GRID_PACK_INT_IDX_GME_NI];
+    gridP->gme.ni2       =   intBuffer[GRID_PACK_INT_IDX_GME_NI2];
+    gridP->gme.ni3       =   intBuffer[GRID_PACK_INT_IDX_GME_NI3];
+    gridP->number        =   intBuffer[GRID_PACK_INT_IDX_NUMBER];
+    gridP->position      =   intBuffer[GRID_PACK_INT_IDX_POSITION];
+    gridP->trunc         =   intBuffer[GRID_PACK_INT_IDX_TRUNC];
+    gridP->nvertex       =   intBuffer[GRID_PACK_INT_IDX_NVERTEX];
+    gridP->nrowlon       =   intBuffer[GRID_PACK_INT_IDX_NROWLON];
+    gridP->size          =   intBuffer[GRID_PACK_INT_IDX_SIZE];
+    gridP->x.size        =   intBuffer[GRID_PACK_INT_IDX_X_SIZE];
+    gridP->y.size        =   intBuffer[GRID_PACK_INT_IDX_Y_SIZE];
+    gridP->lcomplex      =   (bool)intBuffer[GRID_PACK_INT_IDX_LCOMPLEX];
+    memberMask           =   intBuffer[GRID_PACK_INT_IDX_MEMBERMASK];
+    gridP->x.stdname     =
+      xystdname_tab[intBuffer[GRID_PACK_INT_IDX_XTSTDNNAME]][0];
+    gridP->y.stdname     =
+      xystdname_tab[intBuffer[GRID_PACK_INT_IDX_YTSTDNNAME]][1];
+    gridP->uvRelativeToGrid         =   intBuffer[GRID_PACK_INT_IDX_UVRELATIVETOGRID];
+    gridP->iScansNegatively         =   (bool)intBuffer[GRID_PACK_INT_IDX_ISCANSNEGATIVELY];
+    gridP->jScansPositively         =   (bool)intBuffer[GRID_PACK_INT_IDX_JSCANSPOSITIVELY];
+    gridP->jPointsAreConsecutive    =   (bool)intBuffer[GRID_PACK_INT_IDX_JPOINTSARECONSECUTIVE];
+    gridP->scanningMode             =   intBuffer[GRID_PACK_INT_IDX_SCANNINGMODE];
   }
 
   if (memberMask & gridHasRowLonFlag)
@@ -4151,19 +4301,12 @@ gridUnpack(char * unpackBuffer, int unpackBufferSize,
                     &d, 1, CDI_DATATYPE_UINT32, context);
     xassert(d == cdiCheckSum(CDI_DATATYPE_FLT, gridNdouble, doubleBuffer));
 
-    gridP->x.first = doubleBuffer[0];
-    gridP->y.first = doubleBuffer[1];
-    gridP->x.last = doubleBuffer[2];
-    gridP->y.last = doubleBuffer[3];
-    gridP->x.inc = doubleBuffer[4];
-    gridP->y.inc = doubleBuffer[5];
-    gridP->lcc.originLon = doubleBuffer[6];
-    gridP->lcc.originLat = doubleBuffer[7];
-    gridP->lcc.lonParY = doubleBuffer[8];
-    gridP->lcc.lat1 = doubleBuffer[9];
-    gridP->lcc.lat2 = doubleBuffer[10];
-    gridP->lcc.xinc = doubleBuffer[11];
-    gridP->lcc.yinc = doubleBuffer[12];
+    gridP->x.first = doubleBuffer[GRID_PACK_DBL_IDX_X_FIRST];
+    gridP->y.first = doubleBuffer[GRID_PACK_DBL_IDX_Y_FIRST];
+    gridP->x.last = doubleBuffer[GRID_PACK_DBL_IDX_X_LAST];
+    gridP->y.last = doubleBuffer[GRID_PACK_DBL_IDX_Y_LAST];
+    gridP->x.inc = doubleBuffer[GRID_PACK_DBL_IDX_X_INC];
+    gridP->y.inc = doubleBuffer[GRID_PACK_DBL_IDX_Y_INC];
   }
 
   int irregular = gridP->type == GRID_UNSTRUCTURED
@@ -4294,33 +4437,38 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
   {
     int intBuffer[gridNint];
 
-    intBuffer[0]  = gridP->self;
-    intBuffer[1]  = gridP->type;
-    intBuffer[2]  = gridP->prec;
-    intBuffer[3]  = gridP->lcc.projflag;
-    intBuffer[4]  = gridP->lcc.scanflag;
-    intBuffer[5]  = gridP->lcc.defined;
-    intBuffer[8]  = gridP->isCyclic;
-    intBuffer[10] = gridP->x.flag;
-    intBuffer[11] = gridP->y.flag;
-    intBuffer[12] = gridP->gme.nd;
-    intBuffer[13] = gridP->gme.ni;
-    intBuffer[14] = gridP->gme.ni2;
-    intBuffer[15] = gridP->gme.ni3;
-    intBuffer[16] = gridP->number;
-    intBuffer[17] = gridP->position;
-    intBuffer[18] = gridP->trunc;
-    intBuffer[19] = gridP->nvertex;
-    intBuffer[20] = gridP->nrowlon;
-    intBuffer[21] = gridP->size;
-    intBuffer[22] = gridP->x.size;
-    intBuffer[23] = gridP->y.size;
-    intBuffer[24] = gridP->lcomplex;
-    intBuffer[25] = memberMask = gridGetComponentFlags(gridP);
-    intBuffer[26] = (int)((const char (*)[2][24])gridP->x.stdname
-                          - xystdname_tab);
-    intBuffer[27] = (int)((const char (*)[2][24])gridP->y.stdname
-                          - (const char (*)[2][24])xystdname_tab[0][1]);
+    intBuffer[GRID_PACK_INT_IDX_SELF]         = gridP->self;
+    intBuffer[GRID_PACK_INT_IDX_TYPE]         = gridP->type;
+    intBuffer[GRID_PACK_INT_IDX_PREC]         = gridP->prec;
+    intBuffer[GRID_PACK_INT_IDX_IS_CYCLIC]    = gridP->isCyclic;
+    intBuffer[GRID_PACK_INT_IDX_X_FLAG]       = gridP->x.flag;
+    intBuffer[GRID_PACK_INT_IDX_Y_FLAG]       = gridP->y.flag;
+    intBuffer[GRID_PACK_INT_IDX_GME_ND]       = gridP->gme.nd;
+    intBuffer[GRID_PACK_INT_IDX_GME_NI]       = gridP->gme.ni;
+    intBuffer[GRID_PACK_INT_IDX_GME_NI2]      = gridP->gme.ni2;
+    intBuffer[GRID_PACK_INT_IDX_GME_NI3]      = gridP->gme.ni3;
+    intBuffer[GRID_PACK_INT_IDX_NUMBER]       = gridP->number;
+    intBuffer[GRID_PACK_INT_IDX_POSITION]     = gridP->position;
+    intBuffer[GRID_PACK_INT_IDX_TRUNC]        = gridP->trunc;
+    intBuffer[GRID_PACK_INT_IDX_NVERTEX]      = gridP->nvertex;
+    intBuffer[GRID_PACK_INT_IDX_NROWLON]      = gridP->nrowlon;
+    intBuffer[GRID_PACK_INT_IDX_SIZE]         = gridP->size;
+    intBuffer[GRID_PACK_INT_IDX_X_SIZE]       = gridP->x.size;
+    intBuffer[GRID_PACK_INT_IDX_Y_SIZE]       = gridP->y.size;
+    intBuffer[GRID_PACK_INT_IDX_LCOMPLEX]     = gridP->lcomplex;
+    intBuffer[GRID_PACK_INT_IDX_MEMBERMASK]   = memberMask
+                                              = gridGetComponentFlags(gridP);
+    intBuffer[GRID_PACK_INT_IDX_XTSTDNNAME]   =
+      (int)((const char (*)[2][24])gridP->x.stdname - xystdname_tab);
+    intBuffer[GRID_PACK_INT_IDX_YTSTDNNAME]   =
+      (int)((const char (*)[2][24])gridP->y.stdname
+            - (const char (*)[2][24])xystdname_tab[0][1]);
+
+    intBuffer[GRID_PACK_INT_IDX_UVRELATIVETOGRID] = gridP->uvRelativeToGrid;
+    intBuffer[GRID_PACK_INT_IDX_ISCANSNEGATIVELY] = gridP->iScansNegatively;
+    intBuffer[GRID_PACK_INT_IDX_JSCANSPOSITIVELY] = gridP->jScansPositively;
+    intBuffer[GRID_PACK_INT_IDX_JPOINTSARECONSECUTIVE] = gridP->jPointsAreConsecutive;
+    intBuffer[GRID_PACK_INT_IDX_SCANNINGMODE] = gridP->scanningMode;
 
     serializePack(intBuffer, gridNint, CDI_DATATYPE_INT,
                   packBuffer, packBufferSize, packBufferPos, context);
@@ -4343,19 +4491,12 @@ gridPack(void * voidP, void * packBuffer, int packBufferSize,
   {
     double doubleBuffer[gridNdouble];
 
-    doubleBuffer[0]  = gridP->x.first;
-    doubleBuffer[1]  = gridP->y.first;
-    doubleBuffer[2]  = gridP->x.last;
-    doubleBuffer[3]  = gridP->y.last;
-    doubleBuffer[4]  = gridP->x.inc;
-    doubleBuffer[5]  = gridP->y.inc;
-    doubleBuffer[6]  = gridP->lcc.originLon;
-    doubleBuffer[7]  = gridP->lcc.originLat;
-    doubleBuffer[8]  = gridP->lcc.lonParY;
-    doubleBuffer[9]  = gridP->lcc.lat1;
-    doubleBuffer[10] = gridP->lcc.lat2;
-    doubleBuffer[11] = gridP->lcc.xinc;
-    doubleBuffer[12] = gridP->lcc.yinc;
+    doubleBuffer[GRID_PACK_DBL_IDX_X_FIRST]        = gridP->x.first;
+    doubleBuffer[GRID_PACK_DBL_IDX_Y_FIRST]        = gridP->y.first;
+    doubleBuffer[GRID_PACK_DBL_IDX_X_LAST]         = gridP->x.last;
+    doubleBuffer[GRID_PACK_DBL_IDX_Y_LAST]         = gridP->y.last;
+    doubleBuffer[GRID_PACK_DBL_IDX_X_INC]          = gridP->x.inc;
+    doubleBuffer[GRID_PACK_DBL_IDX_Y_INC]          = gridP->y.inc;
 
     serializePack(doubleBuffer, gridNdouble, CDI_DATATYPE_FLT64,
                   packBuffer, packBufferSize, packBufferPos, context);
@@ -4497,7 +4638,7 @@ gridCompareSearch(int id, void *res, void *data)
 {
   struct gridCompareSearchState *state = (struct gridCompareSearchState*)data;
   (void)res;
-  if ( gridCompare(id, state->queryKey, false) == false )
+  if ( gridCompare(id, state->queryKey, true) == false )
     {
       state->resIDValue = id;
       return CDI_APPLY_STOP;
diff --git a/libcdi/src/grid.h b/libcdi/src/grid.h
index 9c41140..d301ab9 100644
--- a/libcdi/src/grid.h
+++ b/libcdi/src/grid.h
@@ -6,6 +6,10 @@
 
 #include "cdi_att.h"
 
+extern double grid_missval;
+extern int (*proj_lonlat_to_lcc_func)();
+extern int (*proj_lcc_to_lonlat_func)();
+
 typedef unsigned char mask_t;
 
 typedef struct grid_t grid_t;
@@ -58,20 +62,6 @@ struct gridaxis_t {
   double *bounds;
 };
 
-// Lambert Conformal Conic
-struct grid_lcc_t {
-  double  originLon;
-  double  originLat;
-  double  lonParY;
-  double  lat1;
-  double  lat2;
-  double  xinc;
-  double  yinc;
-  int     projflag;
-  int     scanflag;
-  short   defined;
-};
-
 // GME Grid
 struct grid_gme_t {
   int     nd, ni, ni2, ni3;       /* parameter for GRID_GME         */
@@ -83,6 +73,7 @@ struct grid_t {
   char    mapping[CDI_MAX_NAME];
   char   *name;
   int     self;
+  int     size;
   int     type;                   /* grid type                      */
   int     prec;                   /* grid precision                 */
   int     proj;                   /* grid projection                */
@@ -90,9 +81,7 @@ struct grid_t {
   mask_t *mask;
   mask_t *mask_gme;
   double *area;
-  struct grid_lcc_t  lcc;
   struct grid_gme_t  gme;
-  short   isCyclic;               /* TRUE for global cyclic grids   */
   int     number, position;       /* parameter for GRID_REFERENCE   */
   int     trunc;                  /* parameter for GRID_SPECTEAL    */
   int     nvertex;
@@ -100,14 +89,27 @@ struct grid_t {
   unsigned char uuid[CDI_UUID_SIZE]; /* uuid for grid reference        */
   int    *rowlon;
   int     nrowlon;
-  int     size;
   int     np;                     /* number of parallels between a pole and the equator */
+  signed char isCyclic;           /* three possible states:
+                                   * -1 if unknown,
+                                   * 0 if found not cyclic, or
+                                   * 1 for global cyclic grids
+                                   */
   bool    lcomplex;
   bool    hasdims;
+  bool uvRelativeToGrid;  /* Some models deliver wind U,V relative to the grid-cell */
   struct gridaxis_t x;
   struct gridaxis_t y;
   const struct gridVirtTable *vtable;
   cdi_atts_t atts;
+  int  scanningMode;
+  bool iScansNegatively, jScansPositively, jPointsAreConsecutive;
+  /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
+               64  = 128 * 0                + 64 *        1         + 32 * 0
+               00  = 128 * 0                + 64 *        0         + 32 * 0
+               96  = 128 * 0                + 64 *        1         + 32 * 1
+     Default / implicit scanning mode is 64:
+                        i and j scan positively, i points are consecutive (row-major)        */
 };
 
 
@@ -149,6 +151,9 @@ struct addIfNewRes
 
 struct addIfNewRes cdiVlistAddGridIfNew(int vlistID, grid_t *grid, int mode);
 
+int gridVerifyGribParamLCC(int gridID, double missval, double *lon_0, double *lat_0, double *lat_1, double *lat_2,
+                           double *a, double *rf, double *xval_0, double *yval_0, double *x_0, double *y_0);
+
 #endif
 /*
  * Local Variables:
diff --git a/libcdi/src/iterator_fallback.c b/libcdi/src/iterator_fallback.c
index 213f85d..34a431a 100644
--- a/libcdi/src/iterator_fallback.c
+++ b/libcdi/src/iterator_fallback.c
@@ -1,3 +1,7 @@
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
 #include "iterator_fallback.h"
 
 #include "cdi.h"
diff --git a/libcdi/src/iterator_fallback.h b/libcdi/src/iterator_fallback.h
index 6c7170f..1b8bda2 100644
--- a/libcdi/src/iterator_fallback.h
+++ b/libcdi/src/iterator_fallback.h
@@ -8,6 +8,12 @@
 #ifndef INCLUDE_GUARD_CDI_ITERATOR_FALLBACK_H
 #define INCLUDE_GUARD_CDI_ITERATOR_FALLBACK_H
 
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <stdlib.h>
+
 #include "cdi.h"
 #include "cdi_int.h"
 #include "iterator.h"
diff --git a/libcdi/src/iterator_grib.c b/libcdi/src/iterator_grib.c
index 496e124..1492da2 100644
--- a/libcdi/src/iterator_grib.c
+++ b/libcdi/src/iterator_grib.c
@@ -1,3 +1,7 @@
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
 #include "iterator_grib.h"
 
 #include "cdi.h"
@@ -25,11 +29,7 @@ struct CdiGribIterator {
   off_t fileOffset;
   unsigned char *gribBuffer;
   size_t bufferSize, curRecordSize;
-#ifdef HAVE_LIBGRIB_API
   grib_handle *gribHandle;
-#else
-  void *gribHandle;
-#endif
 };
 
 CdiIterator *cdiGribIterator_getSuper(CdiGribIterator *me)
@@ -85,7 +85,7 @@ CdiIterator *cdiGribIterator_new(const char *path, int filetype)
 
 CdiGribIterator *cdiGribIterator_makeClone(CdiIterator *super)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   //Allocate memory and copy data. (operations that may fail)
   CdiGribIterator *result = (struct CdiGribIterator *) Malloc(sizeof(*result));
@@ -137,7 +137,7 @@ fail:
 
 char *cdiGribIterator_serialize(CdiIterator *super)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   const char *path = cdiInputFile_getPath(me->file);
   char *escapedPath = cdiEscapeSpaces(path);
@@ -166,7 +166,9 @@ CdiGribIterator *cdiGribIterator_deserialize(const char *description)
 
   {
     const char *savedStart = description;
-    long long decodedOffset = strtoll(description, (char**)&description, 0);    //The cast is a workaround for the wrong signature of strtoll() (it should have been `long long strtoll(const char*, const char**, int)`, not `long long strtoll(const char*, char**, int)`.
+    char *description_ = (char *)description;
+    long long decodedOffset = strtoll(description, &description_, 0);
+    description = description_;
     me->fileOffset = (off_t)decodedOffset;
     if(savedStart == description) goto closeFile;
     if((unsigned long long)decodedOffset > (unsigned long long)me->fileOffset) goto closeFile;
@@ -348,7 +350,7 @@ fail:
 
 int cdiGribIterator_nextField(CdiIterator *super)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   if(super->gridId != CDI_UNDEFID) gridDestroy(super->gridId), super->gridId = CDI_UNDEFID;
 
@@ -369,13 +371,13 @@ int cdiGribIterator_nextField(CdiIterator *super)
 
 char *cdiGribIterator_inqTime(CdiIterator *super, CdiTimeType timeType)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
   return gribMakeTimeString(me->gribHandle, timeType);
 }
 
 int cdiGribIterator_levelType(CdiIterator *super, int levelSelector, char **outName, char **outLongName, char **outStdName, char **outUnit)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   //First determine the zaxis type corresponding to the given level.
   int zaxisType = ZAXIS_GENERIC;
@@ -462,7 +464,7 @@ static int readLevel2(grib_handle *gribHandle, const char *levelTypeKey, const c
 
 int cdiGribIterator_level(CdiIterator *super, int levelSelector, double *outValue1, double *outValue2)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
   double trash;
   if(!outValue1) outValue1 = &trash;
   if(!outValue2) outValue2 = &trash;
@@ -486,15 +488,15 @@ int cdiGribIterator_level(CdiIterator *super, int levelSelector, double *outValu
         {}
       else if(isGrib1DualLevel((int)levelType))
         {
-          *outValue1 = (double)gribGetLongDefault(me->gribHandle, (levelSelector ? "bottomLevel" : "topLevel"), 0);
+          *outValue1 = (double)(gribGetLongDefault(me->gribHandle, (levelSelector ? "bottomLevel" : "topLevel"), 0));
         }
       else if(levelType == 100)
         {
-          *outValue1 = 100 * (double)gribGetLongDefault(me->gribHandle, "level", 0);        //2 bytes
+          *outValue1 = 100 * (double)(gribGetLongDefault(me->gribHandle, "level", 0));        //2 bytes
         }
       else
         {
-          *outValue1 = (double)gribGetLongDefault(me->gribHandle, "level", 0);        //2 bytes
+          *outValue1 = (double)(gribGetLongDefault(me->gribHandle, "level", 0));        //2 bytes
         }
     }
   return CDI_NOERR;
@@ -502,7 +504,7 @@ int cdiGribIterator_level(CdiIterator *super, int levelSelector, double *outValu
 
 int cdiGribIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *outLevelCount, unsigned char outUuid[CDI_UUID_SIZE])
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   if(outVgridNumber)
     {
@@ -528,7 +530,7 @@ int cdiGribIterator_zaxisUuid(CdiIterator *super, int *outVgridNumber, int *outL
 
 int cdiGribIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileAttribute)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
   int trash;
   if(!outTileIndex) outTileIndex = &trash;
   if(!outTileAttribute) outTileAttribute = &trash;
@@ -548,7 +550,7 @@ int cdiGribIterator_inqTile(CdiIterator *super, int *outTileIndex, int *outTileA
 
 int cdiGribIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *outTileAttributeCount)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
   int trash;
   if(!outTileCount) outTileCount = &trash;
   if(!outTileAttributeCount) outTileAttributeCount = &trash;
@@ -568,13 +570,13 @@ int cdiGribIterator_inqTileCount(CdiIterator *super, int *outTileCount, int *out
 
 char *cdiGribIterator_copyVariableName(CdiIterator *super)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
   return gribCopyString(me->gribHandle, "shortName");
 }
 
 void cdiGribIterator_readField(CdiIterator *super, double *buffer, size_t *nmiss)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   GRIB_CHECK(my_grib_set_double(me->gribHandle, "missingValue", cdiDefaultMissval), 0);
   gribGetDoubleArray(me->gribHandle, "values", buffer);
@@ -587,7 +589,7 @@ void cdiGribIterator_readField(CdiIterator *super, double *buffer, size_t *nmiss
 
 void cdiGribIterator_readFieldF(CdiIterator *super, float *buffer, size_t *nmiss)
 {
-  CdiGribIterator *me = (CdiGribIterator*)super;
+  CdiGribIterator *me = (CdiGribIterator*)(void *)super;
 
   size_t valueCount = gribGetArraySize(me->gribHandle, "values");
   double *temp = (double *) Malloc(valueCount*sizeof(*temp));
@@ -643,6 +645,7 @@ int cdiGribIterator_inqEdition(CdiGribIterator *me)
 #else
   (void)me;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -669,6 +672,7 @@ int cdiGribIterator_getLong(CdiGribIterator *me, const char *key, long *result)
   (void)key;
   (void)result;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -701,6 +705,7 @@ int cdiGribIterator_getLength(CdiGribIterator *me, const char *key, size_t *resu
   (void)key;
   (void)result;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -728,6 +733,7 @@ int cdiGribIterator_getString(CdiGribIterator *me, const char *key, char *result
   (void)result;
   (void)length;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -754,6 +760,7 @@ long cdiGribIterator_inqLongValue(CdiGribIterator *me, const char *key)
   (void)me;
   (void)key;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -782,6 +789,7 @@ long cdiGribIterator_inqLongDefaultValue(CdiGribIterator *me, const char *key, l
   (void)key;
   (void)defaultValue;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -809,6 +817,7 @@ char *cdiGribIterator_inqStringValue(CdiGribIterator *me, const char *key)
   (void)me;
   (void)key;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return NULL;
 #endif
 }
 
@@ -835,6 +844,7 @@ int cdiGribIterator_getDouble(CdiGribIterator *me, const char *key, double *resu
   (void)key;
   (void)result;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -861,6 +871,7 @@ int cdiGribIterator_getSize(CdiGribIterator *me, const char *key, size_t *result
   (void)key;
   (void)result;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -888,6 +899,7 @@ int cdiGribIterator_getLongArray(CdiGribIterator *me, const char *key, long *res
   (void)result;
   (void)size;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -915,6 +927,7 @@ int cdiGribIterator_getDoubleArray(CdiGribIterator *me, const char *key, double
   (void)result;
   (void)size;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -941,6 +954,7 @@ double cdiGribIterator_inqDoubleValue(CdiGribIterator *me, const char *key)
   (void)me;
   (void)key;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
@@ -969,6 +983,7 @@ double cdiGribIterator_inqDoubleDefaultValue(CdiGribIterator *me, const char *ke
   (void)key;
   (void)defaultValue;
   xabort("CDI was compiled without GribAPI support, so you can't possibly have a valid CdiGribIterator* to call this function with");
+  return -4;
 #endif
 }
 
diff --git a/libcdi/src/iterator_grib.h b/libcdi/src/iterator_grib.h
index 65b9962..30b3c05 100644
--- a/libcdi/src/iterator_grib.h
+++ b/libcdi/src/iterator_grib.h
@@ -7,6 +7,10 @@
 #ifndef INCLUDE_GUARD_CDI_ITERATOR_GRIB_H
 #define INCLUDE_GUARD_CDI_ITERATOR_GRIB_H
 
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
 #include "cdi.h"
 #include "cdi_int.h"
 #include "iterator.h"
diff --git a/libcdi/src/mo_cdi.f90 b/libcdi/src/mo_cdi.f90
index 4b37d26..ff1edcd 100644
--- a/libcdi/src/mo_cdi.f90
+++ b/libcdi/src/mo_cdi.f90
@@ -543,6 +543,10 @@ module mo_cdi
   public :: gridChangeType
   public :: gridDefComplexPacking
   public :: gridInqComplexPacking
+  public :: gridDefUvRelativeToGrid
+  public :: gridInqUvRelativeToGrid
+  public :: gridDefScanningMode
+  public :: gridInqScanningMode
   public :: zaxisName
   public :: zaxisNamePtr
   public :: zaxisCreate
@@ -2098,37 +2102,43 @@ module mo_cdi
       integer(c_int), intent(inout) :: ni3_dummy
     end subroutine gridInqParamGME
 
-    subroutine gridDefParamLCC(gridID_dummy, originLon_dummy, originLat_dummy,&
-    & lonParY_dummy, lat1_dummy, lat2_dummy, xinc_dummy, yinc_dummy,&
-    & projflag_dummy, scanflag_dummy) bind(c, name = 'gridDefParamLCC')
+    subroutine gridDefParamLCC(gridID_dummy, missval_dummy, lon_0_dummy,&
+    & lat_0_dummy, lat_1_dummy, lat_2_dummy, a_dummy, rf_dummy, xval_0_dummy,&
+    & yval_0_dummy, x_0_dummy, y_0_dummy) bind(c, name = 'gridDefParamLCC')
       import c_double, c_int
       integer(c_int), value :: gridID_dummy
-      real(c_double), value :: originLon_dummy
-      real(c_double), value :: originLat_dummy
-      real(c_double), value :: lonParY_dummy
-      real(c_double), value :: lat1_dummy
-      real(c_double), value :: lat2_dummy
-      real(c_double), value :: xinc_dummy
-      real(c_double), value :: yinc_dummy
-      integer(c_int), value :: projflag_dummy
-      integer(c_int), value :: scanflag_dummy
+      real(c_double), value :: missval_dummy
+      real(c_double), value :: lon_0_dummy
+      real(c_double), value :: lat_0_dummy
+      real(c_double), value :: lat_1_dummy
+      real(c_double), value :: lat_2_dummy
+      real(c_double), value :: a_dummy
+      real(c_double), value :: rf_dummy
+      real(c_double), value :: xval_0_dummy
+      real(c_double), value :: yval_0_dummy
+      real(c_double), value :: x_0_dummy
+      real(c_double), value :: y_0_dummy
     end subroutine gridDefParamLCC
 
-    subroutine gridInqParamLCC(gridID_dummy, originLon_dummy, originLat_dummy,&
-    & lonParY_dummy, lat1_dummy, lat2_dummy, xinc_dummy, yinc_dummy,&
-    & projflag_dummy, scanflag_dummy) bind(c, name = 'gridInqParamLCC')
+    function gridInqParamLCC(gridID_dummy, missval_dummy, lon_0_dummy,&
+    & lat_0_dummy, lat_1_dummy, lat_2_dummy, a_dummy, rf_dummy, xval_0_dummy,&
+    & yval_0_dummy, x_0_dummy, y_0_dummy) bind(c, name = 'gridInqParamLCC')&
+    & result(f_result)
       import c_double, c_int
       integer(c_int), value :: gridID_dummy
-      real(c_double), intent(inout) :: originLon_dummy
-      real(c_double), intent(inout) :: originLat_dummy
-      real(c_double), intent(inout) :: lonParY_dummy
-      real(c_double), intent(inout) :: lat1_dummy
-      real(c_double), intent(inout) :: lat2_dummy
-      real(c_double), intent(inout) :: xinc_dummy
-      real(c_double), intent(inout) :: yinc_dummy
-      integer(c_int), intent(inout) :: projflag_dummy
-      integer(c_int), intent(inout) :: scanflag_dummy
-    end subroutine gridInqParamLCC
+      real(c_double), value :: missval_dummy
+      real(c_double), intent(inout) :: lon_0_dummy
+      real(c_double), intent(inout) :: lat_0_dummy
+      real(c_double), intent(inout) :: lat_1_dummy
+      real(c_double), intent(inout) :: lat_2_dummy
+      real(c_double), intent(inout) :: a_dummy
+      real(c_double), intent(inout) :: rf_dummy
+      real(c_double), intent(inout) :: xval_0_dummy
+      real(c_double), intent(inout) :: yval_0_dummy
+      real(c_double), intent(inout) :: x_0_dummy
+      real(c_double), intent(inout) :: y_0_dummy
+      integer(c_int) :: f_result
+    end function gridInqParamLCC
 
     subroutine gridDefArea(gridID_dummy, area_dummy) bind(c, name =&
     & 'gridDefArea')
@@ -2231,6 +2241,34 @@ module mo_cdi
       integer(c_int) :: f_result
     end function gridInqComplexPacking
 
+    subroutine gridDefUvRelativeToGrid(gridID_dummy, uvRelativeToGrid_dummy)&
+    & bind(c, name = 'gridDefUvRelativeToGrid')
+      import c_int
+      integer(c_int), value :: gridID_dummy
+      integer(c_int), value :: uvRelativeToGrid_dummy
+    end subroutine gridDefUvRelativeToGrid
+
+    function gridInqUvRelativeToGrid(gridID_dummy) bind(c, name =&
+    & 'gridInqUvRelativeToGrid') result(f_result)
+      import c_int
+      integer(c_int), value :: gridID_dummy
+      integer(c_int) :: f_result
+    end function gridInqUvRelativeToGrid
+
+    subroutine gridDefScanningMode(gridID_dummy, mode_dummy) bind(c, name =&
+    & 'gridDefScanningMode')
+      import c_int
+      integer(c_int), value :: gridID_dummy
+      integer(c_int), value :: mode_dummy
+    end subroutine gridDefScanningMode
+
+    function gridInqScanningMode(gridID_dummy) bind(c, name =&
+    & 'gridInqScanningMode') result(f_result)
+      import c_int
+      integer(c_int), value :: gridID_dummy
+      integer(c_int) :: f_result
+    end function gridInqScanningMode
+
     function zaxisCreate(zaxistype_dummy, size_dummy) bind(c, name =&
     & 'zaxisCreate') result(f_result)
       import c_int
diff --git a/libcdi/src/pio_interface.c b/libcdi/src/pio_interface.c
index 37b2f03..da371c6 100644
--- a/libcdi/src/pio_interface.c
+++ b/libcdi/src/pio_interface.c
@@ -2,7 +2,7 @@
 #  include "config.h"
 #endif
 
-#include <stdint.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdlib.h>
@@ -340,7 +340,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos,
   unsigned char *dstBuf = (unsigned char *)buf + pos_,
     *bufEnd = (unsigned char *)buf + size;
   size_t elemSize = p->elemSize;
-  xassert(elemSize <= SIZE_MAX);
+  xassert(elemSize <= SSIZE_MAX);
   const unsigned char *data = p->data;
   unsigned copyCount = 0, numElems = p->numElems;
   for (unsigned j = 0; j < numBlocks && copyCount < numElems; ++j)
@@ -356,7 +356,7 @@ scatterGatherPackFunc(void *dataDesc, void *buf, int size, int *pos,
             }
           size_t bsize = (size_t)bl * elemSize;
           xassert(dstBuf + bsize <= bufEnd);
-          memcpy(dstBuf, data + (size_t)elemSize * (size_t)disps[j], bsize);
+          memcpy(dstBuf, data + (ssize_t)elemSize * (ssize_t)disps[j], bsize);
           dstBuf += bsize;
         }
     }
diff --git a/libcdi/src/pio_mpi_fw_at_all.c b/libcdi/src/pio_mpi_fw_at_all.c
index a470d17..22366c9 100644
--- a/libcdi/src/pio_mpi_fw_at_all.c
+++ b/libcdi/src/pio_mpi_fw_at_all.c
@@ -117,7 +117,7 @@ fwFileWriteAtAll(int fileID, const void *buffer, size_t len)
     rankPio = commInqRankPio();
   /* find position to write to */
   of->collWriteSize[rankPio] = (int)len;
-  xmpi(MPI_Allgather(MPI_IN_PLACE, 0, MPI_CDI_DATATYPE_NULL,
+  xmpi(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
                      of->collWriteSize, 1, MPI_INT, commPio));
   MPI_Offset myPos = of->pos, nextWritePos;
   for (size_t i = 0; i < (size_t)rankPio; ++i)
diff --git a/libcdi/src/pio_mpi_fw_at_reblock.c b/libcdi/src/pio_mpi_fw_at_reblock.c
index c60df0d..e945fda 100644
--- a/libcdi/src/pio_mpi_fw_at_reblock.c
+++ b/libcdi/src/pio_mpi_fw_at_reblock.c
@@ -355,7 +355,7 @@ fwFileWriteAtReblock(int fileID, const void *buffer, size_t len)
     rankPio = commInqRankPio();
   /* find position to write to */
   of->collWriteSize[rankPio] = (long)len;
-  xmpi(MPI_Allgather(MPI_IN_PLACE, 0, MPI_CDI_DATATYPE_NULL,
+  xmpi(MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
                      of->collWriteSize, 1, MPI_LONG, commPio));
   /* figure out which block buffers intersect locally held data and
    * what remotely held data intersects buffers on task */
diff --git a/libcdi/src/pio_roles.c b/libcdi/src/pio_roles.c
index 1946e28..20f3153 100644
--- a/libcdi/src/pio_roles.c
+++ b/libcdi/src/pio_roles.c
@@ -117,7 +117,7 @@ cdiPioCSRBalanced(MPI_Comm commSuper, int IOMode, int nProcsIO)
     if (commRank == commSize - 1)
       role = specialRole;
     else if (commRank <= clientsPerCollectorMax * (nProcsIO - 1 - rest))
-      role = (commRank + 1 % (clientsPerCollectorMax + 1)) != 0
+      role = ((commRank + 1) % (clientsPerCollectorMax + 1)) != 0
         ? PIO_ROLE_CLIENT : collType;
     else
       role = ((commRank - clientsPerCollectorMax * (nProcsIO - 1 - rest) + 1)
diff --git a/libcdi/src/pio_util.c b/libcdi/src/pio_util.c
index 529d2ed..e1ef723 100644
--- a/libcdi/src/pio_util.c
+++ b/libcdi/src/pio_util.c
@@ -184,7 +184,7 @@ cdiPioQueryVarDims(int varShape[3], int vlistID, int varID)
       varShape[1] = gridInqSize(gridID) / 2;
       break;
     case GRID_GENERIC:
-    case GRID_LCC:
+    case GRID_PROJECTION:
     case GRID_GME:
     case GRID_CURVILINEAR:
     case GRID_UNSTRUCTURED:
diff --git a/libcdi/src/pio_util.h b/libcdi/src/pio_util.h
index 47ff0a8..0126f68 100644
--- a/libcdi/src/pio_util.h
+++ b/libcdi/src/pio_util.h
@@ -8,7 +8,7 @@
 
 #include <mpi.h>
 
-#ifndef _ERROR_H
+#ifndef ERROR_H
 #include "error.h"
 #endif
 
diff --git a/libcdi/src/pkgconfig/cdi.pc.in b/libcdi/src/pkgconfig/cdi.pc.in
index 0cbd19e..5d76a92 100644
--- a/libcdi/src/pkgconfig/cdi.pc.in
+++ b/libcdi/src/pkgconfig/cdi.pc.in
@@ -4,7 +4,7 @@ libdir=@libdir@
 includedir=@includedir@
 cflags=-I at includedir@
 fcflags=@FPP_INCOPT@@includedir@ @CDI_F90_INTERFACE_FCFLAGS@
-libs=-L at libdir@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@
+libs=-L at libdir@ -lcdi @GRIB_API_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@ @LIBS@
 threads_libs=@THREADS_LIBS@
 threads_cflags=@THREADS_INCLUDE@
 szlib_cflags=@SZLIB_INCLUDE@
@@ -12,7 +12,7 @@ szlib_libs=@SZLIB_LIBS@
 netcdf_root=@NETCDF_ROOT@
 netcdf_cflags=@NETCDF_INCLUDE@
 netcdf_libs=@NETCDF_LIBS@
-jasper_libs=@JASPER_LIBS@
+aux_libs=@LIBS@
 grib_api_cflags=@GRIB_API_INCLUDE@
 grib_api_libs=@GRIB_API_LIBS@
 cdi_build_cc=@CC@
diff --git a/libcdi/src/pkgconfig/cdipio.pc.in b/libcdi/src/pkgconfig/cdipio.pc.in
index b8020c8..7b34f21 100644
--- a/libcdi/src/pkgconfig/cdipio.pc.in
+++ b/libcdi/src/pkgconfig/cdipio.pc.in
@@ -4,7 +4,7 @@ libdir=@libdir@
 includedir=@includedir@
 cflags=-I at includedir@
 fcflags=@FPP_INCOPT@@includedir@ @CDI_F90_INTERFACE_FCFLAGS@
-libs=-L at libdir@ -lcdipio @PPM_CORE_LIBS@ @YAXT_LIBS@ -lcdi @GRIB_API_LIBS@ @JASPER_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@
+libs=-L at libdir@ -lcdipio @PPM_CORE_LIBS@ @YAXT_LIBS@ -lcdi @GRIB_API_LIBS@ @NETCDF_LIBS@ @SZLIB_LIBS@ @THREADS_LIBS@ @LIBS@
 threads_libs=@THREADS_LIBS@
 threads_cflags=@THREADS_INCLUDE@
 szlib_cflags=@SZLIB_INCLUDE@
@@ -12,9 +12,9 @@ szlib_libs=@SZLIB_LIBS@
 netcdf_root=@NETCDF_ROOT@
 netcdf_cflags=@NETCDF_INCLUDE@
 netcdf_libs=@NETCDF_LIBS@
-jasper_libs=@JASPER_LIBS@
 grib_api_cflags=@GRIB_API_INCLUDE@
 grib_api_libs=@GRIB_API_LIBS@
+aux_libs=@LIBS@
 cdipio_build_cc=@CC@
 cdipio_build_cflags=@CFLAGS@
 cdipio_build_cppflags=@CPPFLAGS@
diff --git a/libcdi/src/serialize.h b/libcdi/src/serialize.h
index f60cab5..dc0e6b9 100644
--- a/libcdi/src/serialize.h
+++ b/libcdi/src/serialize.h
@@ -11,7 +11,7 @@
 #ifndef  CDI_CKSUM_H_
 #include "cdi_cksum.h"
 #endif
-#ifndef  _ERROR_H
+#ifndef  ERROR_H
 #include "error.h"
 #endif
 
diff --git a/libcdi/src/stream.c b/libcdi/src/stream.c
index 844d706..b4020ca 100644
--- a/libcdi/src/stream.c
+++ b/libcdi/src/stream.c
@@ -637,6 +637,11 @@ int streamOpenA(const char *filename, const char *filemode, int filetype)
   if ( status < 0 ) return status;
   vlist_t *vlistptr = vlist_to_pointer(streamptr->vlistID);
   vlistptr->ntsteps = (int)cdiInqTimeSize(streamID);
+
+  // Needed for NetCDF4
+  for ( int varID = 0; varID < vlistptr->nvars; ++varID )
+    streamptr->vars[varID].defmiss = true;
+
   if ( !strcmp(filemode, "r") ) cdiVlistMakeImmutable(streamptr->vlistID);
 
   {
@@ -972,6 +977,11 @@ void cdiStreamCloseDefaultDelegate(stream_t *streamptr, int recordBufIsToBeDelet
       case CDI_FILETYPE_NC4C:
         {
           cdfClose(fileID);
+          if (streamptr->ntsteps == 0)
+            {
+              Free(streamptr->tsteps[0].records);
+              Free(streamptr->tsteps[0].recIDs);
+            }
           break;
         }
 #endif
@@ -1349,15 +1359,14 @@ void streamWriteContents(int streamID, char *cname)
 
   if ( cnp == NULL ) SysError(cname);
 
-  fprintf(cnp, "#CDI library version %s\n", cdiLibraryVersion());
-  fprintf(cnp, "#\n");
+  fprintf(cnp, "#CDI library version %s\n"
+          "#\n", cdiLibraryVersion());
 
-  fprintf(cnp, "filename: %s\n", streamptr->filename);
   int filetype = streamptr->filetype;
-  fprintf(cnp, "filetype: %s\n", strfiletype(filetype));
+  fprintf(cnp, "filename: %s\n"
+          "filetype: %s\n", streamptr->filename, strfiletype(filetype));
 
-  fprintf(cnp, "#\n");
-  fprintf(cnp, "#grids:\n");
+  fputs("#\n#grids:\n", cnp);
 
   int ngrids = vlistNgrids(vlistID);
   for ( int i = 0; i < ngrids; i++ )
@@ -1369,9 +1378,7 @@ void streamWriteContents(int streamID, char *cname)
       fprintf(cnp, "%4d:%4d:%4d:%4d\n", i+1, gridtype, xsize, ysize);
     }
 
-  fprintf(cnp, "#\n");
-
-  fprintf(cnp, "varID:code:gridID:zaxisID:tsteptype:datatype\n");
+  fputs("#\nvarID:code:gridID:zaxisID:tsteptype:datatype\n", cnp);
 
   int nvars = vlistNvars(vlistID);
   for ( int varID = 0; varID < nvars; varID++ )
@@ -1385,9 +1392,7 @@ void streamWriteContents(int streamID, char *cname)
 	      varID+1, code, gridID, zaxisID, tsteptype, datatype);
     }
 
-  fprintf(cnp, "#\n");
-
-  fprintf(cnp, "tsID:nrecs:date:time\n");
+  fputs("#\ntsID:nrecs:date:time\n", cnp);
 
   int tsID = 0;
   while (1)
@@ -1406,9 +1411,7 @@ void streamWriteContents(int streamID, char *cname)
 	break;
     }
 
-  fprintf(cnp, "#\n");
-
-  fprintf(cnp, "tsID:recID:varID:levID:size:pos\n");
+  fputs("#\ntsID:recID:varID:levID:size:pos\n", cnp);
 
   tsID = 0;
   while (1)
diff --git a/libcdi/src/stream_cdf_i.c b/libcdi/src/stream_cdf_i.c
index 8eb7510..1421164 100644
--- a/libcdi/src/stream_cdf_i.c
+++ b/libcdi/src/stream_cdf_i.c
@@ -203,50 +203,48 @@ int setBaseTime(const char *timeunits, taxis_t *taxis)
   int rdate = -1, rtime = -1;
 
   size_t len = strlen(timeunits);
-  char *tu = (char*) Malloc((len+1) * sizeof(char));
-  memcpy(tu, timeunits, (len+1) * sizeof(char));
-  char *ptu = tu;
+  char *restrict tu = (char *)Malloc((len+1) * sizeof(char));
 
-  for ( size_t i = 0; i < len; i++ ) ptu[i] = (char)tolower((int) ptu[i]);
+  for ( size_t i = 0; i < len; i++ ) tu[i] = (char)tolower((int)timeunits[i]);
+  tu[len] = 0;
 
-  int timeunit = get_timeunit(len, ptu);
+  int timeunit = get_timeunit(len, tu);
   if ( timeunit == -1 )
     {
       Message("Unsupported TIMEUNIT: %s!", timeunits);
       return 1;
     }
 
-  while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
-  if ( *ptu )
+  size_t pos = 0;
+  while ( ! isspace(tu[pos]) && tu[pos] != 0 ) ++pos;
+  if ( tu[pos] )
     {
-      while ( isspace(*ptu) ) ptu++;
+      while ( isspace(tu[pos]) ) ++pos;
 
-      if ( str_is_equal(ptu, "as") )
-        timetype = TAXIS_ABSOLUTE;
-      else if ( str_is_equal(ptu, "since") )
+      if ( str_is_equal(tu+pos, "since") )
         timetype = TAXIS_RELATIVE;
 
-      while ( ! isspace(*ptu) && *ptu != 0 ) ptu++;
-      if ( *ptu )
+      while ( ! isspace(tu[pos]) && tu[pos] != 0 ) ++pos;
+      if ( tu[pos] )
         {
-          while ( isspace(*ptu) ) ptu++;
+          while ( isspace(tu[pos]) ) ++pos;
 
           if ( timetype == TAXIS_ABSOLUTE )
             {
-              if ( !str_is_equal(ptu, "%y%m%d.%f") && timeunit == TUNIT_DAY )
+              if ( !str_is_equal(tu+pos, "%y%m%d.%f") && timeunit == TUNIT_DAY )
                 {
-                  Message("Unsupported format %s for TIMEUNIT day!", ptu);
+                  Message("Unsupported format %s for TIMEUNIT day!", tu+pos);
                   timeunit = -1;
                 }
-              else if ( !str_is_equal(ptu, "%y%m.%f") && timeunit == TUNIT_MONTH )
+              else if ( !str_is_equal(tu+pos, "%y%m.%f") && timeunit == TUNIT_MONTH )
                 {
-                  Message("Unsupported format %s for TIMEUNIT month!", ptu);
+                  Message("Unsupported format %s for TIMEUNIT month!", tu+pos);
                   timeunit = -1;
                 }
             }
           else if ( timetype == TAXIS_RELATIVE )
             {
-              scanTimeString(ptu, &rdate, &rtime);
+              scanTimeString(tu+pos, &rdate, &rtime);
 
               (*taxis).rdate = rdate;
               (*taxis).rtime = rtime;
@@ -395,15 +393,13 @@ void cdfGetAttText(int fileID, int ncvarid, const char *attname, size_t attlen,
 }
 
 static
-bool xtypeIsText(nc_type xtype)
+bool xtypeIsText(int xtype)
 {
-  bool isText = false;
-
-  if      ( xtype == NC_CHAR ) isText = true;
+  bool isText = ( xtype == NC_CHAR )
 #if  defined  (HAVE_NETCDF4)
-  else if ( xtype == NC_STRING ) isText = true;
+    || ( xtype == NC_STRING )
 #endif
-
+    ;
   return isText;
 }
 
@@ -462,13 +458,20 @@ void cdf_scale_add(size_t size, double *data, double addoffset, double scalefact
   bool laddoffset   = IS_NOT_EQUAL(addoffset, 0);
   bool lscalefactor = IS_NOT_EQUAL(scalefactor, 1);
 
-  if ( laddoffset || lscalefactor )
+  if ( laddoffset && lscalefactor )
     {
-      for ( size_t i = 0; i < size; ++i )
-        {
-          if ( lscalefactor ) data[i] *= scalefactor;
-          if ( laddoffset )   data[i] += addoffset;
-        }
+      for (size_t i = 0; i < size; ++i )
+        data[i] = data[i] * scalefactor + addoffset;
+    }
+  else if (lscalefactor)
+    {
+      for (size_t i = 0; i < size; ++i )
+        data[i] *= scalefactor;
+    }
+  else if (laddoffset)
+    {
+      for (size_t i = 0; i < size; ++i )
+        data[i] += addoffset;
     }
 }
 
@@ -1085,7 +1088,14 @@ void cdf_scan_var_attr(int nvars, ncvar_t *ncvars, ncdim_t *ncdims, int timedimi
           int storage_in;
           nc_inq_var_deflate(ncid, ncvarid, &shuffle, &deflate, &deflate_level);
           if ( deflate > 0 ) ncvars[ncvarid].deflate = 1;
-
+          /*
+          size_t cache_size, nelems;
+          float preemption;
+          nc_get_chunk_cache(&cache_size, &nelems, &preemption);
+          printf("cache_size %lu nelems %lu preemption %g\n", cache_size, nelems, preemption);
+          nc_get_var_chunk_cache(ncid, ncvarid, &cache_size, &nelems, &preemption);
+          printf("varid %d cache_size %lu nelems %lu preemption %g\n", ncvarid, cache_size, nelems, preemption);
+          */
           if ( nc_inq_var_chunking(ncid, ncvarid, &storage_in, chunks) == NC_NOERR )
             {
               if ( storage_in == NC_CHUNKED )
@@ -1588,10 +1598,9 @@ void cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 	  for ( int i = 0; i < ndims; i++ )
 	    {
 	      int ncdimid = ncvars[ncvarid].dimids[i];
-	      if      ( ncdims[ncdimid].dimtype == X_AXIS ) cdf_set_dim(ncvars, ncvarid, i, X_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == Y_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Y_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == Z_AXIS ) cdf_set_dim(ncvars, ncvarid, i, Z_AXIS);
-	      else if ( ncdims[ncdimid].dimtype == T_AXIS ) cdf_set_dim(ncvars, ncvarid, i, T_AXIS);
+              int dimtype = ncdims[ncdimid].dimtype;
+	      if ( dimtype >= X_AXIS && dimtype <= T_AXIS )
+                cdf_set_dim(ncvars, ncvarid, i, dimtype);
 	    }
 
 	  if ( CDI_Debug )
@@ -1612,9 +1621,10 @@ void cdf_set_dimtype(int nvars, ncvar_t *ncvars, ncdim_t *ncdims)
 	  int ndims = ncvars[ncvarid].ndims;
 	  for ( int i = 0; i < ndims; i++ )
 	    {
-	      if      ( ncvars[ncvarid].dimtype[i] == X_AXIS ) lxdim = true;
-	      else if ( ncvars[ncvarid].dimtype[i] == Y_AXIS ) lydim = true;
-	      else if ( ncvars[ncvarid].dimtype[i] == Z_AXIS ) lzdim = true;
+              int dimtype = ncvars[ncvarid].dimtype[i];
+              lxdim = lxdim | (dimtype == X_AXIS);
+	      lydim = lydim | (dimtype == Y_AXIS);
+	      lzdim = lzdim | (dimtype == Z_AXIS);
 	      /* else if ( ncvars[ncvarid].dimtype[i] == T_AXIS ) ltdim = true; */
 	    }
 
@@ -1926,10 +1936,8 @@ void grid_set_chunktype(grid_t *grid, ncvar_t *ncvar)
 
       if ( grid->type == GRID_UNSTRUCTURED )
         {
-          if ( ncvar->chunks[ndims-1] == grid->size )
-            ncvar->chunktype = CDI_CHUNK_GRID;
-          else
-            ncvar->chunktype = CDI_CHUNK_AUTO;
+          ncvar->chunktype = ncvar->chunks[ndims-1] == grid->size
+            ? CDI_CHUNK_GRID : CDI_CHUNK_AUTO;
         }
       else
         {
@@ -2319,7 +2327,7 @@ bool cdf_read_coordinates(struct cdfLazyGrid *restrict lazyGrid, ncvar_t *ncvar,
                   {
                     *vdimid = ncvars[bvarid].dimids[nbdims-1];
                     grid->nvertex = (int)ncdims[*vdimid].len;
-                    cdf_load_bounds(grid->size*grid->nvertex, &ncvars[xvarid], &grid->x.bounds, &lazyGrid->xBoundsGet);
+                    cdf_load_bounds(size*(size_t)grid->nvertex, &ncvars[xvarid], &grid->x.bounds, &lazyGrid->xBoundsGet);
                   }
               }
           }
@@ -2337,7 +2345,7 @@ bool cdf_read_coordinates(struct cdfLazyGrid *restrict lazyGrid, ncvar_t *ncvar,
                         *vdimid = ncvars[bvarid].dimids[nbdims-1];
                         grid->nvertex = (int)ncdims[*vdimid].len;
                       }
-                    cdf_load_bounds(grid->size*grid->nvertex, &ncvars[yvarid], &grid->y.bounds, &lazyGrid->yBoundsGet);
+                    cdf_load_bounds(size*(size_t)grid->nvertex, &ncvars[yvarid], &grid->y.bounds, &lazyGrid->yBoundsGet);
                   }
               }
           }
@@ -2772,10 +2780,10 @@ void cdf_define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int
 	      if ( ncvars[zvarid].bounds != CDI_UNDEFID )
 		{
 		  int nbdims = ncvars[ncvars[zvarid].bounds].ndims;
-		  if ( nbdims == 2 )
+		  if ( nbdims == 2 || is_scalar )
 		    {
-		      int nlevel  = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
-		      int nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1]].len;
+		      int nlevel  = is_scalar ? 1 : (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[0]].len;
+		      int nvertex = (int)ncdims[ncvars[ncvars[zvarid].bounds].dimids[1-is_scalar]].len;
 		      if ( nlevel == zsize && nvertex == 2 )
 			{
 			  with_bounds = true;
@@ -2822,13 +2830,13 @@ void cdf_define_all_zaxes(stream_t *streamptr, int vlistID, ncdim_t *ncdims, int
           if ( zaxisType == ZAXIS_HYBRID )
             {
               if ( psvarid != -1 )
-                cdiZaxisDefKeyStr(zaxisID, CDI_KEY_PSNAME, strlen(ncvars[psvarid].name)+1, ncvars[psvarid].name);
+                cdiZaxisDefKeyStr(zaxisID, CDI_KEY_PSNAME, (int)(strlen(ncvars[psvarid].name)+1), ncvars[psvarid].name);
               if ( p0varid != -1 )
                 {
                   double px = 1;
                   cdf_get_var_double(ncvars[p0varid].ncid, p0varid, &px);
                   cdiZaxisDefKeyFlt(zaxisID, CDI_KEY_P0VALUE, px);
-                  cdiZaxisDefKeyStr(zaxisID, CDI_KEY_P0NAME, strlen(ncvars[p0varid].name)+1, ncvars[p0varid].name);
+                  cdiZaxisDefKeyStr(zaxisID, CDI_KEY_P0NAME, (int)(strlen(ncvars[p0varid].name)+1), ncvars[p0varid].name);
                 }
             }
 
@@ -3007,11 +3015,11 @@ void cdf_define_all_vars(stream_t *streamptr, int vlistID, int instID, int model
       int ndims = ncvars[ncvarid].ndims;
       int iodim = 0;
       int ixyz = 0;
-      int ipow10[4] = {1, 10, 100, 1000};
+      static const int ipow10[4] = {1, 10, 100, 1000};
 
       if ( ncvars[ncvarid].tsteptype != TSTEP_CONSTANT ) iodim++;
 
-      int *dimids = ncvars[ncvarid].dimids;
+      const int *dimids = ncvars[ncvarid].dimids;
 
       if ( gridInqType(gridID) == GRID_UNSTRUCTURED && ndims-iodim <= 2 && ydimid == xdimid )
         {
@@ -3451,7 +3459,7 @@ void cdf_set_ucla_dimtype(int ndims, ncdim_t *ncdims, ncvar_t *ncvars)
 }
 
 static
-int cdf_check_vars(int nvars, ncvar_t *ncvars, int ntsteps, int timedimid)
+int cdf_check_vars(int nvars, ncvar_t *ncvars, size_t ntsteps, int timedimid)
 {
   for ( int ncvarid = 0; ncvarid < nvars; ncvarid++ )
     {
@@ -3627,7 +3635,7 @@ int cdfInqContents(stream_t *streamptr)
   size_t ntsteps = 0;
   if ( timedimid != CDI_UNDEFID ) cdf_inq_dimlen(fileID, timedimid, &ntsteps);
 
-  if ( CDI_Debug ) Message("Number of timesteps = %d", ntsteps);
+  if ( CDI_Debug ) Message("Number of timesteps = %zu", ntsteps);
   if ( CDI_Debug ) Message("Time dimid = %d", streamptr->basetime.ncdimid);
 
   /* read ncdims */
@@ -3726,8 +3734,8 @@ int cdfInqContents(stream_t *streamptr)
       ncvar_t *ncvar = &ncvars[ncvarid];
       if ( ncvar->isvar == TRUE && ncvar->ncoordvars )
 	{
-	  int ndims = ncvar->ncoordvars;
-	  for ( int i = 0; i < ndims; i++ )
+	  int ncoordvars = ncvar->ncoordvars;
+	  for ( int i = 0; i < ncoordvars; i++ )
 	    {
 	      if      ( ncvars[ncvar->coordvarids[i]].islon ||
                         ncvars[ncvar->coordvarids[i]].isx )   ncvar->xvarid = ncvar->coordvarids[i];
@@ -3767,7 +3775,7 @@ int cdfInqContents(stream_t *streamptr)
   nvars_data = nvarids;
 
   if ( CDI_Debug ) Message("time varid = %d", streamptr->basetime.ncvarid);
-  if ( CDI_Debug ) Message("ntsteps = %d", ntsteps);
+  if ( CDI_Debug ) Message("ntsteps = %zu", ntsteps);
   if ( CDI_Debug ) Message("nvars_data = %d", nvars_data);
 
 
@@ -3829,6 +3837,9 @@ int cdfInqContents(stream_t *streamptr)
       if ( ncvars[nctimevarid].longname[0] )
         ptaxisDefLongname(taxis, ncvars[nctimevarid].longname);
 
+      if ( ncvars[nctimevarid].units[0] )
+        ptaxisDefUnits(taxis, ncvars[nctimevarid].units);
+
       int datatype = (ncvars[nctimevarid].xtype == NC_FLOAT) ? CDI_DATATYPE_FLT32 : CDI_DATATYPE_FLT64;
       ptaxisDefDatatype(taxis, datatype);
     }
diff --git a/libcdi/src/stream_cdf_o.c b/libcdi/src/stream_cdf_o.c
index c86a9a2..91e612b 100644
--- a/libcdi/src/stream_cdf_o.c
+++ b/libcdi/src/stream_cdf_o.c
@@ -65,12 +65,11 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       streamptr->ncmode = 2;
     }
 
-  size_t index = (size_t)tsID;
-
   double timevalue = cdiEncodeTimeval(taxis->vdate, taxis->vtime, &streamptr->tsteps[0].taxis);
   if ( CDI_Debug ) Message("tsID = %d  timevalue = %f", tsID, timevalue);
 
   int ncvarid = streamptr->basetime.ncvarid;
+  size_t index = (size_t)tsID;
   cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
 
   if ( taxis->has_bounds )
@@ -94,10 +93,6 @@ void cdfDefTimeValue(stream_t *streamptr, int tsID)
       timevalue = taxis->fc_period;
       cdf_put_var1_double(fileID, ncvarid, &index, &timevalue);
     }
-
-  /*
-printf("fileID = %d %d %d %f\n", fileID, time_varid, index, timevalue);
-  */
 }
 
 static
@@ -119,7 +114,7 @@ int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *t
   if ( taxis->climatology )
     {
       static const char climatology_bndsName[] = "climatology_bnds",
-        climatology_bndsAttName[] = "climatology";
+                        climatology_bndsAttName[] = "climatology";
       bndsAttName = climatology_bndsAttName;
       bndsAttValLen = sizeof (climatology_bndsName) - 1;
       bndsAttVal = climatology_bndsName;
@@ -143,42 +138,46 @@ int cdfDefTimeBounds(int fileID, int nctimevarid, int nctimedimid, const char *t
 }
 
 static
-void cdfDefTimeUnits(char *unitstr, taxis_t* taxis0, taxis_t* taxis)
+void cdfDefTimeUnits(char *unitstr, taxis_t *taxis0, taxis_t *taxis)
 {
-  unitstr[0] = 0;
-
-  if ( taxis0->type == TAXIS_ABSOLUTE )
+  if ( taxis->units && taxis->units[0] )
     {
-      if ( taxis0->unit == TUNIT_YEAR )
-        sprintf(unitstr, "year as %s", "%Y.%f");
-      else if ( taxis0->unit == TUNIT_MONTH )
-        sprintf(unitstr, "month as %s", "%Y%m.%f");
-      else
-        sprintf(unitstr, "day as %s", "%Y%m%d.%f");
+      strcpy(unitstr, taxis->units);
     }
   else
     {
-      int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
-      int rdate    = taxis->rdate;
-      int rtime    = taxis->rtime;
-      if ( rdate == -1 )
+      unitstr[0] = 0;
+
+      if ( taxis0->type == TAXIS_ABSOLUTE )
         {
-          rdate  = taxis->vdate;
-          rtime  = taxis->vtime;
+          if      ( taxis0->unit == TUNIT_YEAR  ) sprintf(unitstr, "year as %s", "%Y.%f");
+          else if ( taxis0->unit == TUNIT_MONTH ) sprintf(unitstr, "month as %s", "%Y%m.%f");
+          else                                    sprintf(unitstr, "day as %s", "%Y%m%d.%f");
         }
+      else
+        {
+          int timeunit = taxis->unit != -1 ? taxis->unit : TUNIT_HOUR;
+          int rdate    = taxis->rdate;
+          int rtime    = taxis->rtime;
+          if ( rdate == -1 )
+            {
+              rdate  = taxis->vdate;
+              rtime  = taxis->vtime;
+            }
 
-      int year, month, day, hour, minute, second;
-      cdiDecodeDate(rdate, &year, &month, &day);
-      cdiDecodeTime(rtime, &hour, &minute, &second);
+          int year, month, day, hour, minute, second;
+          cdiDecodeDate(rdate, &year, &month, &day);
+          cdiDecodeTime(rtime, &hour, &minute, &second);
 
-      if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
-      if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
-      if ( timeunit == TUNIT_3HOURS  ||
-	   timeunit == TUNIT_6HOURS  ||
-	   timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
+          if ( timeunit == TUNIT_QUARTER   ) timeunit = TUNIT_MINUTE;
+          if ( timeunit == TUNIT_30MINUTES ) timeunit = TUNIT_MINUTE;
+          if ( timeunit == TUNIT_3HOURS  ||
+               timeunit == TUNIT_6HOURS  ||
+               timeunit == TUNIT_12HOURS ) timeunit = TUNIT_HOUR;
 
-      sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
-              tunitNamePtr(timeunit), year, month, day, hour, minute, second);
+          sprintf(unitstr, "%s since %d-%d-%d %02d:%02d:%02d",
+                  tunitNamePtr(timeunit), year, month, day, hour, minute, second);
+        }
     }
 }
 
@@ -249,6 +248,14 @@ void cdfDefTime(stream_t* streamptr)
 
   streamptr->basetime.ncvarid = time_varid;
 
+#if  defined  (HAVE_NETCDF4)
+  if ( streamptr->filetype == CDI_FILETYPE_NC4 || streamptr->filetype == CDI_FILETYPE_NC4C )
+    {
+      size_t chunk = 512;
+      cdf_def_var_chunking(fileID, time_varid, NC_CHUNKED, &chunk);
+    }
+#endif
+
   {
     static const char timeStr[] = "time";
     cdf_put_att_text(fileID, time_varid, "standard_name", sizeof(timeStr) - 1, timeStr);
@@ -289,9 +296,7 @@ void cdfDefTime(stream_t* streamptr)
   if ( taxis->type == TAXIS_FORECAST )
     {
       int leadtimeid;
-
       cdf_def_var(fileID, "leadtime", xtype, 1, &time_dimid, &leadtimeid);
-
       streamptr->basetime.leadtimeid = leadtimeid;
 
       {
@@ -817,7 +822,7 @@ void cdfGridCompress(int fileID, int ncvarid, int gridsize, int filetype, int co
 #if  defined  (HAVE_NETCDF4)
   if ( gridsize > 1 && comptype == CDI_COMPRESS_ZIP && (filetype == CDI_FILETYPE_NC4 || filetype == CDI_FILETYPE_NC4C) )
     {
-      nc_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
+      cdf_def_var_chunking(fileID, ncvarid, NC_CHUNKED, NULL);
       cdfDefVarDeflate(fileID, ncvarid, 1);
     }
 #endif
@@ -829,7 +834,6 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID, int gridindex)
   int xdimID = CDI_UNDEFID;
   int ydimID = CDI_UNDEFID;
   int ncxvarid = CDI_UNDEFID, ncyvarid = CDI_UNDEFID;
-  int ncbxvarid = CDI_UNDEFID, ncbyvarid = CDI_UNDEFID, ncavarid = CDI_UNDEFID;
   nc_type xtype = (nc_type)cdfDefDatatype(gridInqPrec(gridID), streamptr->filetype);
   ncgrid_t *ncgrid = streamptr->ncgrid;
 
@@ -864,6 +868,7 @@ void cdfDefCurvilinear(stream_t *streamptr, int gridID, int gridindex)
         }
     }
 
+  int ncbxvarid = CDI_UNDEFID, ncbyvarid = CDI_UNDEFID, ncavarid = CDI_UNDEFID;
   if ( xdimID == CDI_UNDEFID || ydimID == CDI_UNDEFID )
     {
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
@@ -1231,7 +1236,9 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
 
       cdfDefGridUUID(streamptr, gridID);
 
-      if ( gridInqXvalsPtr(gridID) )
+      const double *xvalsPtr = gridInqXvalsPtr(gridID),
+        *xboundsPtr = NULL;
+      if ( xvalsPtr )
         {
           char xaxisname[CDI_MAX_NAME]; xaxisname[0] = 0;
           cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xaxisname);
@@ -1241,7 +1248,7 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
 
           cdfPutGridStdAtts(fileID, ncxvarid, gridID, 'X', &gridInqsX);
 
-          if ( gridInqXboundsPtr(gridID) && nvdimID != CDI_UNDEFID )
+          if ( (xboundsPtr = gridInqXboundsPtr(gridID)) && nvdimID != CDI_UNDEFID )
             {
               int dimIDs[2] = { dimID, nvdimID };
               size_t xaxisnameLen = strlen(xaxisname);
@@ -1254,7 +1261,9 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
             }
         }
 
-      if ( gridInqYvalsPtr(gridID) )
+      const double *yvalsPtr = gridInqYvalsPtr(gridID),
+        *yboundsPtr = NULL;
+      if ( yvalsPtr )
         {
           char yaxisname[CDI_MAX_NAME];
           gridInqYname(gridID, yaxisname);
@@ -1264,7 +1273,8 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
 
           cdfPutGridStdAtts(fileID, ncyvarid, gridID, 'Y', &gridInqsY);
 
-          if ( gridInqYboundsPtr(gridID) && nvdimID != CDI_UNDEFID )
+          if ( (yboundsPtr = gridInqYboundsPtr(gridID))
+               && nvdimID != CDI_UNDEFID )
             {
               int dimIDs[2] = { dimID, nvdimID };
               size_t yaxisnameLen = strlen(yaxisname);
@@ -1277,7 +1287,8 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
             }
         }
 
-      if ( gridInqAreaPtr(gridID) )
+      const double *areaPtr = gridInqAreaPtr(gridID);
+      if ( areaPtr )
         {
           static const char yaxisname_[] = "cell_area";
           static const char units[] = "m2";
@@ -1294,11 +1305,11 @@ void cdfDefUnstructured(stream_t *streamptr, int gridID, int gridindex)
       cdf_enddef(fileID);
       streamptr->ncmode = 2;
 
-      if ( ncxvarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  gridInqXvalsPtr(gridID));
-      if ( ncbxvarid != CDI_UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, gridInqXboundsPtr(gridID));
-      if ( ncyvarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  gridInqYvalsPtr(gridID));
-      if ( ncbyvarid != CDI_UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, gridInqYboundsPtr(gridID));
-      if ( ncavarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncavarid,  gridInqAreaPtr(gridID));
+      if ( ncxvarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncxvarid,  xvalsPtr);
+      if ( ncbxvarid != CDI_UNDEFID ) cdf_put_var_double(fileID, ncbxvarid, xboundsPtr);
+      if ( ncyvarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncyvarid,  yvalsPtr);
+      if ( ncbyvarid != CDI_UNDEFID ) cdf_put_var_double(fileID, ncbyvarid, yboundsPtr);
+      if ( ncavarid  != CDI_UNDEFID ) cdf_put_var_double(fileID, ncavarid,  areaPtr);
     }
 
   ncgrid[gridindex].gridID = gridID;
@@ -1337,7 +1348,7 @@ void cdf_def_vct_echam(stream_t *streamptr, int zaxisID)
 
       if ( streamptr->ncmode == 2 ) cdf_redef(fileID);
 
-      int ncdimid, ncdimid2 = -1;
+      int ncdimid = -1, ncdimid2 = -1;
       int hyaiid, hybiid, hyamid = -1, hybmid = -1;
 
       cdf_def_dim(fileID, "nhyi", (size_t)ilev, &ncdimid2);
@@ -2042,12 +2053,6 @@ void cdfDefGrid(stream_t *streamptr, int gridID, int gridindex)
       cdfDefTrajLon(streamptr, gridID, gridindex);
       cdfDefTrajLat(streamptr, gridID, gridindex);
     }
-  /*
-  else if ( gridtype == GRID_LCC )
-    {
-      cdfDefLcc(streamptr, gridID);
-    }
-  */
   else
     {
       Error("Unsupported grid type: %s", gridNamePtr(gridtype));
@@ -2064,14 +2069,13 @@ void cdfDefHistory(stream_t *streamptr, int size, const char *history)
 
 void cdfDefVars(stream_t *streamptr)
 {
-  int index = 0;
   int vlistID = streamptr->vlistID;
   if ( vlistID == CDI_UNDEFID )
     Error("Internal problem! vlist undefined for streamptr %p", streamptr);
 
   int ngrids = vlistNgrids(vlistID);
-  if ( 2*ngrids > MAX_GRIDS_PS ) Error("Internaal problem! Too many grids per stream (max=%d)\n", MAX_GRIDS_PS);
-  for ( index = 0; index < 2*ngrids; ++index )
+  if ( 2*ngrids > MAX_GRIDS_PS ) Error("Internal problem! Too many grids per stream (max=%d)\n", MAX_GRIDS_PS);
+  for ( int index = 0; index < 2*ngrids; ++index )
     {
       streamptr->ncgrid[index].gridID = CDI_UNDEFID;
       streamptr->ncgrid[index].xdimID = CDI_UNDEFID;
@@ -2081,19 +2085,20 @@ void cdfDefVars(stream_t *streamptr)
       streamptr->ncgrid[index].avarID = CDI_UNDEFID;
     }
 
-  for ( index = 0; index < ngrids; ++index )
+  for ( int index = 0; index < ngrids; ++index )
     {
       int gridID = vlistGrid(vlistID, index);
       cdfDefGrid(streamptr, gridID, index);
     }
-  index = ngrids-1;
-  for ( int i = 0; i < ngrids; ++i )
-    {
-      int gridID = vlistGrid(vlistID, i);
-      int projID = gridInqProj(gridID);
-      if ( projID != CDI_UNDEFID ) cdfDefGrid(streamptr, projID, ++index);
-    }
-
+  {
+    int index = ngrids-1;
+    for ( int i = 0; i < ngrids; ++i )
+      {
+        int gridID = vlistGrid(vlistID, i);
+        int projID = gridInqProj(gridID);
+        if ( projID != CDI_UNDEFID ) cdfDefGrid(streamptr, projID, ++index);
+      }
+  }
   int nzaxis = vlistNzaxis(vlistID);
   for ( int index = 0; index < nzaxis; ++index )
     {
diff --git a/libcdi/src/stream_cgribex.c b/libcdi/src/stream_cgribex.c
index 5173931..d963571 100644
--- a/libcdi/src/stream_cgribex.c
+++ b/libcdi/src/stream_cgribex.c
@@ -39,12 +39,7 @@ int cgribexGetGridType(int *isec2)
     case  GRIB1_GTYPE_LATLON:     { gridtype = GRID_LONLAT;     break; }
     case  GRIB1_GTYPE_LATLON_ROT: { gridtype = GRID_PROJECTION; break; }
     case  GRIB1_GTYPE_LCC:        { gridtype = GRID_LCC;        break; }
-    case  GRIB1_GTYPE_GAUSSIAN:   { if ( ISEC2_Reduced )
-	                              gridtype = GRID_GAUSSIAN_REDUCED;
-                         	    else
-				      gridtype = GRID_GAUSSIAN;
-          	                    break;
-                                  }
+    case  GRIB1_GTYPE_GAUSSIAN:   { gridtype = ISEC2_Reduced ? GRID_GAUSSIAN_REDUCED : GRID_GAUSSIAN; break; }
     case  GRIB1_GTYPE_SPECTRAL:   { gridtype = GRID_SPECTRAL;   break; }
     case  GRIB1_GTYPE_GME:        { gridtype = GRID_GME;        break; }
     }
@@ -116,9 +111,9 @@ bool cgribexTimeIsFC(int *isec1)
 static
 int cgribexGetTsteptype(int timerange)
 {
-  int tsteptype = TSTEP_INSTANT;
   static bool lprint = true;
 
+  int tsteptype = TSTEP_INSTANT;
   switch ( timerange )
     {
     case  0:  tsteptype = TSTEP_INSTANT;  break;
@@ -146,11 +141,16 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
   bool compyinc = true;
   int gridtype = cgribexGetGridType(isec2);
   int projtype = (gridtype == GRID_PROJECTION && cgribexGetIsRotated(isec2)) ? CDI_PROJ_RLL : CDI_UNDEFID;
+  if ( gridtype == GRID_LCC )
+    {
+      gridtype = GRID_PROJECTION;
+      projtype = CDI_PROJ_LCC;
+    }
 
   if ( streamptr->unreduced && gridtype == GRID_GAUSSIAN_REDUCED && iret != -801 )
     {
-      int ilat, nlon = 0;
-      for ( ilat = 0; ilat < ISEC2_NumLat; ++ilat )
+      int nlon = 0;
+      for ( int ilat = 0; ilat < ISEC2_NumLat; ++ilat )
         if ( ISEC2_RowLon(ilat) > nlon ) nlon = ISEC2_RowLon(ilat);
       gridtype = GRID_GAUSSIAN;
       ISEC2_NumLon = nlon;
@@ -163,9 +163,14 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
 
   if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || projtype == CDI_PROJ_RLL )
     {
+      bool ijDirectionIncrementGiven = gribbyte_get_bit(ISEC2_ResFlag, 1);
+      bool uvRelativeToGrid = gribbyte_get_bit(ISEC2_ResFlag, 5);
+
+      if ( uvRelativeToGrid ) grid->uvRelativeToGrid = 1;
       if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
         Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
-      grid->size  = ISEC4_NumValues;
+
+      grid->size   = ISEC4_NumValues;
       grid->x.size = ISEC2_NumLon;
       grid->y.size = ISEC2_NumLat;
       if ( gridtype == GRID_GAUSSIAN ) grid->np = ISEC2_NumPar;
@@ -180,7 +185,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
 
             if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
 
-            if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+            if ( ijDirectionIncrementGiven && ISEC2_LonIncr > 0 )
               {
                 if ( abs(ISEC2_LastLon - (ISEC2_FirstLon+ISEC2_LonIncr*(grid->x.size-1))) <= 2 )
                   {
@@ -213,7 +218,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
         if ( grid->y.size > 1 && compyinc )
           {
             bool recompinc = true;
-            if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+            if ( ijDirectionIncrementGiven && ISEC2_LatIncr > 0 )
               {
                 if ( abs(ISEC2_LastLat - (ISEC2_FirstLat+ISEC2_LatIncr*(grid->y.size-1))) <= 2 )
                   {
@@ -232,6 +237,9 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
     }
   else if ( gridtype == GRID_GAUSSIAN_REDUCED )
     {
+      bool ijDirectionIncrementGiven = gribbyte_get_bit(ISEC2_ResFlag, 1);
+      bool uvRelativeToGrid = gribbyte_get_bit(ISEC2_ResFlag, 5);
+      if ( uvRelativeToGrid ) grid->uvRelativeToGrid = 1;
       grid->np      = ISEC2_NumPar;
       grid->size    = ISEC4_NumValues;
       grid->rowlon  = ISEC2_RowLonPtr;
@@ -246,7 +254,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
           {
             if ( ISEC2_LastLon < ISEC2_FirstLon && ISEC2_LastLon < 0 ) ISEC2_LastLon += 360000;
 
-            if ( ISEC2_ResFlag && ISEC2_LonIncr > 0 )
+            if ( ijDirectionIncrementGiven && ISEC2_LonIncr > 0 )
               grid->x.inc = ISEC2_LonIncr * 0.001;
             else
               grid->x.inc = (ISEC2_LastLon - ISEC2_FirstLon) * 0.001 / (grid->x.size - 1);
@@ -260,7 +268,7 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
       {
         if ( grid->y.size > 1 )
           {
-            if ( ISEC2_ResFlag && ISEC2_LatIncr > 0 )
+            if ( ijDirectionIncrementGiven && ISEC2_LatIncr > 0 )
               grid->y.inc = ISEC2_LatIncr * 0.001;
             else
               grid->y.inc = (ISEC2_LastLat - ISEC2_FirstLat) * 0.001 / (grid->y.size - 1);
@@ -270,28 +278,26 @@ void cgribexGetGrid(stream_t *streamptr, int *isec2, int *isec4, grid_t *grid, i
         grid->y.flag  = 2;
       }
     }
-  else if ( gridtype == GRID_LCC )
+  else if ( projtype == CDI_PROJ_LCC )
     {
+      bool uvRelativeToGrid = gribbyte_get_bit(ISEC2_ResFlag, 5);
+      if ( uvRelativeToGrid ) grid->uvRelativeToGrid = 1;
+
       if ( ISEC4_NumValues != ISEC2_NumLon*ISEC2_NumLat )
-        Error("numberOfPoints (%d) and gridSize (%d) differ!",
-              ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
+        Error("numberOfPoints (%d) and gridSize (%d) differ!", ISEC4_NumValues, ISEC2_NumLon*ISEC2_NumLat);
 
-      grid->size  = ISEC4_NumValues;
+      grid->size   = ISEC4_NumValues;
       grid->x.size = ISEC2_NumLon;
       grid->y.size = ISEC2_NumLat;
 
-      grid->lcc.xinc      = ISEC2_Lambert_dx;
-      grid->lcc.yinc      = ISEC2_Lambert_dy;
-      grid->lcc.originLon = ISEC2_FirstLon * 0.001;
-      grid->lcc.originLat = ISEC2_FirstLat * 0.001;
-      grid->lcc.lonParY   = ISEC2_Lambert_Lov * 0.001;
-      grid->lcc.lat1      = ISEC2_Lambert_LatS1 * 0.001;
-      grid->lcc.lat2      = ISEC2_Lambert_LatS2 * 0.001;
-      grid->lcc.projflag  = ISEC2_Lambert_ProjFlag;
-      grid->lcc.scanflag  = ISEC2_ScanFlag;
-
-      grid->x.flag = 0;
-      grid->y.flag = 0;
+      grid->x.first = 0;
+      grid->x.last  = 0;
+      grid->x.inc   = ISEC2_Lambert_dx;
+      grid->y.first = 0;
+      grid->y.last  = 0;
+      grid->y.inc   = ISEC2_Lambert_dy;
+      grid->x.flag  = 2;
+      grid->y.flag  = 2;
     }
   else if ( gridtype == GRID_SPECTRAL )
     {
@@ -384,6 +390,32 @@ void cgribexAddRecord(stream_t * streamptr, int param, int *isec1, int *isec2, d
           double angle = - FSEC2_RotAngle;
           gridDefParamRLL(gridID, xpole, ypole, angle);
         }
+      else if ( gridptr->projtype == CDI_PROJ_LCC )
+        {
+          double a = 6367470., rf = 0;
+          bool earthIsOblate = gribbyte_get_bit(ISEC2_ResFlag, 2);
+          if ( earthIsOblate ) { a = 6378160.; rf = 297.0; }
+          double xval_0 = ISEC2_FirstLon * 0.001;
+          double yval_0 = ISEC2_FirstLat * 0.001;
+          double lon_0  = ISEC2_Lambert_Lov * 0.001;
+          double lat_1  = ISEC2_Lambert_LatS1 * 0.001;
+          double lat_2  = ISEC2_Lambert_LatS2 * 0.001;
+          bool lsouth = gribbyte_get_bit(ISEC2_Lambert_ProjFlag, 1);
+          if ( lsouth ) { lat_1 = -lat_1; lat_2 = -lat_2; }
+
+          double lat_0 = lat_2;
+          double x_0 = grid_missval;
+          double y_0 = grid_missval;
+
+          if ( proj_lonlat_to_lcc_func )
+            {
+              x_0 = xval_0; y_0 = yval_0;
+              proj_lonlat_to_lcc_func(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, (size_t)1, &x_0, &y_0);
+              if ( IS_NOT_EQUAL(x_0, grid_missval) && IS_NOT_EQUAL(y_0, grid_missval) )
+                { x_0 = -x_0; y_0 = -y_0; }
+            }
+          gridDefParamLCC(gridID, grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0);
+        }
     }
   else
     Free(gridptr);
@@ -494,7 +526,6 @@ void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
   if ( ISEC1_CenterID == 215 && (isec1[34] != 0 && isec1[34] != 255) )
     {
       double undef_pds, undef_eps;
-
       MCH_get_undef(isec1, &undef_pds, &undef_eps);
       FSEC3_MissVal = undef_pds;
       *lmv = 1;
@@ -504,9 +535,9 @@ void cgribexDecodeHeader(int *isec0, int *isec1, int *isec2, double *fsec2,
 static
 compvar_t cgribexVarSet(int param, int level1, int level2, int leveltype, int trange)
 {
-  compvar_t compVar;
   int tsteptype = cgribexGetTsteptype(trange);
 
+  compvar_t compVar;
   compVar.param     = param;
   compVar.level1    = level1;
   compVar.level2    = level2;
@@ -667,10 +698,7 @@ int cgribexScanTimestep1(stream_t *streamptr)
 
       gribDateTime(isec1, &vdate, &vtime);
 
-      if ( ISEC4_NumBits > 0 && ISEC4_NumBits <= 32 )
-	datatype = ISEC4_NumBits;
-      else
-        datatype = CDI_DATATYPE_PACK;
+      datatype = (ISEC4_NumBits > 0 && ISEC4_NumBits <= 32) ? ISEC4_NumBits : CDI_DATATYPE_PACK;
 
       if ( nrecs == 0 )
 	{
@@ -1353,33 +1381,18 @@ int cgribexDecode(int memtype, void *gribbuffer, int gribsize, void *data, long
 static
 void cgribexDefInstitut(int *isec1, int vlistID, int varID)
 {
-  int instID;
-
-  if ( vlistInqInstitut(vlistID) != CDI_UNDEFID )
-    instID = vlistInqInstitut(vlistID);
-  else
-    instID = vlistInqVarInstitut(vlistID, varID);
-
+  int instID = (vlistInqInstitut(vlistID) != CDI_UNDEFID) ? vlistInqInstitut(vlistID) : vlistInqVarInstitut(vlistID, varID);
   if ( instID != CDI_UNDEFID )
     {
-      int center, subcenter;
-      center    = institutInqCenter(instID);
-      subcenter = institutInqSubcenter(instID);
-      ISEC1_CenterID    = center;
-      ISEC1_SubCenterID = subcenter;
+      ISEC1_CenterID    = institutInqCenter(instID);
+      ISEC1_SubCenterID = institutInqSubcenter(instID);
     }
 }
 
 static
 void cgribexDefModel(int *isec1, int vlistID, int varID)
 {
-  int modelID;
-
-  if ( vlistInqModel(vlistID) != CDI_UNDEFID )
-    modelID = vlistInqModel(vlistID);
-  else
-    modelID = vlistInqVarModel(vlistID, varID);
-
+  int modelID = (vlistInqModel(vlistID) != CDI_UNDEFID) ? vlistInqModel(vlistID) : vlistInqVarModel(vlistID, varID);
   if ( modelID != CDI_UNDEFID )
     ISEC1_ModelID = modelInqGribID(modelID);
 }
@@ -1388,9 +1401,7 @@ static
 void cgribexDefParam(int *isec1, int param)
 {
   int pdis, pcat, pnum;
-
   cdiDecodeParam(param, &pnum, &pcat, &pdis);
-
   if ( pnum < 0 ) pnum = -pnum;
 
   static bool lwarn_pdis = true;
@@ -1418,10 +1429,8 @@ static
 int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 			int rdate, int rtime, int vdate, int vtime, int *pip1, int *pip2)
 {
-  int timerange = -1;
   int year, month, day, hour, minute, second;
   int julday1, secofday1, julday2, secofday2, days, secs;
-  int ip1 = 0, ip2 = 0;
 
   cdiDecodeDate(rdate, &year, &month, &day);
   cdiDecodeTime(rtime, &hour, &minute, &second);
@@ -1433,6 +1442,8 @@ int cgribexDefTimerange(int tsteptype, int factor, int calendar,
 
   (void) julday_sub(julday1, secofday1, julday2, secofday2, &days, &secs);
 
+  int timerange = -1;
+  int ip1 = 0, ip2 = 0;
   if ( !(int)(fmod(days*86400.0 + secs, factor)) )
     {
       int ip = (int) ((days*86400.0 + secs)/factor);
@@ -1462,13 +1473,10 @@ static
 int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
 {
   int year, month, day, hour, minute, second;
-  int century = 0;
-  int factor = 1;
-
   cdiDecodeDate(date, &year, &month, &day);
   cdiDecodeTime(time, &hour, &minute, &second);
 
-  century =  year / 100;
+  int century =  year / 100;
 
   ISEC1_Year = year - century*100;
 
@@ -1494,6 +1502,7 @@ int cgribexDefDateTime(int *isec1, int timeunit, int date, int time)
 
   ISEC1_Century = century;
 
+  int factor = 1;
   switch (timeunit)
     {
     case TUNIT_MINUTE:    factor =    60; ISEC1_TimeUnit = ISEC1_TABLE4_MINUTE;    break;
@@ -1650,10 +1659,17 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
         }
     }
 
-  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+  if ( gridtype == GRID_PROJECTION )
     {
-      gridtype = GRID_LONLAT;
-      lrotated = true;
+      if ( gridInqProjType(gridID) == CDI_PROJ_RLL )
+        {
+          gridtype = GRID_LONLAT;
+          lrotated = true;
+        }
+      else if ( gridInqProjType(gridID) == CDI_PROJ_LCC )
+        {
+          gridtype = GRID_LCC;
+        }
     }
 
   ISEC2_Reduced  = FALSE;
@@ -1692,7 +1708,7 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	      {
 		xfirst = gridInqXval(gridID, 0);
                 xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
-		xinc   = gridInqXinc(gridID);
+		xinc   = fabs(gridInqXinc(gridID));
 	      }
 	  }
 
@@ -1730,7 +1746,6 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	else
 	  {
 	    ISEC2_LatIncr = (int)lround(yinc*1000);
-	    if ( ISEC2_LatIncr < 0 ) ISEC2_LatIncr = -ISEC2_LatIncr;
 	  }
 
 	if ( ISEC2_NumLon > 1 && ISEC2_NumLat == 1 )
@@ -1739,7 +1754,9 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	if ( ISEC2_NumLon == 1 && ISEC2_NumLat > 1 )
 	  if ( ISEC2_LonIncr == 0 && ISEC2_LatIncr != 0 ) ISEC2_LonIncr = ISEC2_LatIncr;
 
-        ISEC2_ResFlag = ( ISEC2_LatIncr == 0 || ISEC2_LonIncr == 0 ) ? 0 : 128;
+        ISEC2_ResFlag = 0;
+        if ( ISEC2_LatIncr && ISEC2_LonIncr )   gribbyte_set_bit(&ISEC2_ResFlag, 1);
+        if ( gridInqUvRelativeToGrid(gridID) )  gribbyte_set_bit(&ISEC2_ResFlag, 5);
 
 	if ( lrotated )
           {
@@ -1752,40 +1769,49 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
             FSEC2_RotAngle = angle;
           }
 
-	/* East -> West */
-	if ( ISEC2_LastLon < ISEC2_FirstLon ) ISEC2_ScanFlag += 128;
-
-	/* South -> North */
-	if ( ISEC2_LastLat > ISEC2_FirstLat ) ISEC2_ScanFlag += 64;
+        ISEC2_ScanFlag = 0;
+	if ( ISEC2_LastLon < ISEC2_FirstLon ) gribbyte_set_bit(&ISEC2_ScanFlag, 1); // East -> West
+	if ( ISEC2_LastLat > ISEC2_FirstLat ) gribbyte_set_bit(&ISEC2_ScanFlag, 2); // South -> North
 
 	break;
       }
     case GRID_LCC:
       {
-	double originLon = 0.0, originLat = 0.0, lonParY = 0.0,
-          lat1 = 0.0, lat2 = 0.0, xincm = 0.0, yincm = 0.0;
-	int projflag = 0, scanflag = 0;
+	int xsize = gridInqXsize(gridID);
+        int ysize = gridInqYsize(gridID);
 
-	int xsize = gridInqXsize(gridID),
-          ysize = gridInqYsize(gridID);
+        double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+	gridInqParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+	gridVerifyGribParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+        bool lsouth = (lat_1 < 0);
+        if ( lsouth ) { lat_1 = -lat_2; lat_2 = -lat_2; }
 
-	gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-		   &projflag, &scanflag);
+        double xinc = gridInqXinc(gridID);
+        double yinc = gridInqYinc(gridID);
 
 	ISEC2_GridType = GRIB1_GTYPE_LCC;
 	ISEC2_NumLon   = xsize;
 	ISEC2_NumLat   = ysize;
-	ISEC2_FirstLon = (int)lround(originLon * 1000);
-	ISEC2_FirstLat = (int)lround(originLat * 1000);
-	ISEC2_Lambert_Lov    = (int)lround(lonParY * 1000);
-	ISEC2_Lambert_LatS1  = (int)lround(lat1 * 1000);
-	ISEC2_Lambert_LatS2  = (int)lround(lat2 * 1000);
-	ISEC2_Lambert_dx     = (int)lround(xincm);
-	ISEC2_Lambert_dy     = (int)lround(yincm);
+	ISEC2_FirstLon       = (int)lround(xval_0 * 1000);
+	ISEC2_FirstLat       = (int)lround(yval_0 * 1000);
+	ISEC2_Lambert_Lov    = (int)lround(lon_0 * 1000);
+	ISEC2_Lambert_LatS1  = (int)lround(lat_1 * 1000);
+	ISEC2_Lambert_LatS2  = (int)lround(lat_2 * 1000);
+	ISEC2_Lambert_dx     = (int)lround(xinc);
+	ISEC2_Lambert_dy     = (int)lround(yinc);
 	ISEC2_Lambert_LatSP  = 0;
 	ISEC2_Lambert_LonSP  = 0;
-	ISEC2_Lambert_ProjFlag = projflag;
-	ISEC2_ScanFlag = scanflag;
+	ISEC2_Lambert_ProjFlag = 0;
+        if ( lsouth ) gribbyte_set_bit(&ISEC2_Lambert_ProjFlag, 1);
+
+        bool earthIsOblate = (IS_EQUAL(a, 6378160.) && IS_EQUAL(rf, 297.));
+        ISEC2_ResFlag = 0;
+        if ( ISEC2_Lambert_dx && ISEC2_Lambert_dy ) gribbyte_set_bit(&ISEC2_ResFlag, 1);
+        if ( earthIsOblate )                        gribbyte_set_bit(&ISEC2_ResFlag, 2);
+        if ( gridInqUvRelativeToGrid(gridID) )      gribbyte_set_bit(&ISEC2_ResFlag, 5);
+
+	ISEC2_ScanFlag = 0;
+        gribbyte_set_bit(&ISEC2_ScanFlag, 2); // South -> North
 
 	break;
       }
@@ -1836,6 +1862,18 @@ void cgribexDefGrid(int *isec1, int *isec2, double *fsec2, int *isec4, int gridI
 	break;
       }
     }
+
+
+  if ( cdiGribChangeModeUvRelativeToGrid.active )
+    {
+      // this will overrule/change the UvRelativeToGrid flag;
+      // typically when the wind is rotated with respect to north pole
+      bool uvRelativeToGrid = gribbyte_get_bit(ISEC2_ResFlag, 5);
+      if      ( uvRelativeToGrid && !cdiGribChangeModeUvRelativeToGrid.mode )
+        gribbyte_clear_bit(&ISEC2_ResFlag, 5);
+      else if ( !uvRelativeToGrid && cdiGribChangeModeUvRelativeToGrid.mode )
+        gribbyte_set_bit(&ISEC2_ResFlag, 5);
+    }
 }
 
 static
@@ -1851,7 +1889,6 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
 {
   char units[CDI_MAX_NAME];
   static bool lwarning_vct = true;
-  double level;
 
   int zaxistype = zaxisInqType(zaxisID);
   int ltype = zaxisInqLtype(zaxisID);
@@ -1877,7 +1914,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_DEPTH_BELOW_SEA:
     case ZAXIS_ISENTROPIC:
       {
-        isec1DefLevel(isec1, grib_ltype, (int) zaxisInqLevel(zaxisID, levelID), 0);
+        isec1DefLevel(isec1, grib_ltype, (int)(zaxisInqLevel(zaxisID, levelID)), 0);
 	break;
       }
     case ZAXIS_CLOUD_BASE:
@@ -1894,10 +1931,10 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_HYBRID_HALF:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID),
-                        (int)zaxisInqUbound(zaxisID, levelID));
+          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID_LAYER, (int)(zaxisInqLbound(zaxisID, levelID)),
+                        (int)(zaxisInqUbound(zaxisID, levelID)));
 	else
-          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID, (int) zaxisInqLevel(zaxisID, levelID), 0);
+          isec1DefLevel(isec1, GRIB1_LTYPE_HYBRID, (int)(zaxisInqLevel(zaxisID, levelID)), 0);
 
 	int vctsize = zaxisInqVctSize(zaxisID);
 	if ( vctsize > 255 )
@@ -1918,7 +1955,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
       }
     case ZAXIS_PRESSURE:
       {
-	level = zaxisInqLevel(zaxisID, levelID);
+	double level = zaxisInqLevel(zaxisID, levelID);
 	if ( level < 0 ) Warning("Pressure level of %f Pa is below zero!", level);
 
 	zaxisInqUnits(zaxisID, units);
@@ -1935,7 +1972,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
       }
     case ZAXIS_HEIGHT:
       {
-	level = zaxisInqLevel(zaxisID, levelID);
+	double level = zaxisInqLevel(zaxisID, levelID);
 
 	zaxisInqUnits(zaxisID, units);
         if ( units[1] == 'm' && !units[2] )
@@ -1951,10 +1988,10 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
     case ZAXIS_SIGMA:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA_LAYER, (int) zaxisInqLbound(zaxisID, levelID),
-                        (int) zaxisInqUbound(zaxisID, levelID));
+          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA_LAYER, (int)(zaxisInqLbound(zaxisID, levelID)),
+                        (int)(zaxisInqUbound(zaxisID, levelID)));
 	else
-          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA, (int) zaxisInqLevel(zaxisID, levelID), 0);
+          isec1DefLevel(isec1, GRIB1_LTYPE_SIGMA, (int)(zaxisInqLevel(zaxisID, levelID)), 0);
 
 	break;
       }
@@ -1962,11 +1999,10 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
       {
 	zaxisInqUnits(zaxisID, units);
 
-	double factor;
+	double factor = 100; // default: meter
         if      ( units[0] == 'm' && units[1] == 'm' ) factor =   0.1;
         else if ( units[0] == 'c' && units[1] == 'm' ) factor =   1;
         else if ( units[0] == 'd' && units[1] == 'm' ) factor =  10;
-        else                                           factor = 100; // meter
 
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
           isec1DefLevel(isec1, GRIB1_LTYPE_LANDDEPTH_LAYER, (int) (factor*zaxisInqLbound(zaxisID, levelID)),
@@ -1978,7 +2014,7 @@ void cgribexDefLevel(int *isec1, int *isec2, double *fsec2, int zaxisID, int lev
       }
     case ZAXIS_GENERIC:
       {
-        isec1DefLevel(isec1, ltype, (int) zaxisInqLevel(zaxisID, levelID), 0);
+        isec1DefLevel(isec1, ltype, (int)(zaxisInqLevel(zaxisID, levelID)), 0);
 	break;
       }
     default:
@@ -2044,21 +2080,17 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
 		     int vdate, int vtime, int tsteptype, int numavg,
 		     long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize)
 {
-  size_t nbytes = 0;
-  int gribsize;
   int iret = 0, iword = 0;
   int isec0[2], isec1[4096], isec2[4096], isec3[2], isec4[512];
   float fsec2f[512], fsec3f[2];
   double fsec2[512], fsec3[2];
-  int datatype;
-  int param;
 
   memset(isec1, 0, 256*sizeof(int));
   fsec2[0] = 0; fsec2[1] = 0;
   fsec2f[0] = 0; fsec2f[1] = 0;
 
-  gribsize = (int)(gribbuffersize / sizeof(int));
-  param    = vlistInqVarParam(vlistID, varID);
+  int gribsize = (int)(gribbuffersize / sizeof(int));
+  int param    = vlistInqVarParam(vlistID, varID);
 
   cgribexDefaultSec0(isec0);
   cgribexDefaultSec1(isec1);
@@ -2067,7 +2099,7 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
   cgribexDefInstitut(isec1, vlistID, varID);
   cgribexDefModel(isec1, vlistID, varID);
 
-  datatype = vlistInqVarDatatype(vlistID, varID);
+  int datatype = vlistInqVarDatatype(vlistID, varID);
 
   cgribexDefParam(isec1, param);
   cgribexDefTime(isec1, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID));
@@ -2112,9 +2144,70 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
 
   if ( iret ) Error("Problem during GRIB encode (errno = %d)!", iret);
 
-  nbytes = (size_t)iword * sizeof (int);
+  size_t nbytes = (size_t)iword * sizeof(int);
   return nbytes;
 }
+
+
+typedef struct
+{
+  void *gribbuffer;
+  size_t gribbuffersize;
+  unsigned char *pds;
+  unsigned char *gds;
+  unsigned char *bms;
+  unsigned char *bds;
+} cgribex_handle;
+
+
+int grib1Sections(unsigned char *gribbuffer, long gribbufsize, unsigned char **pdsp,
+		  unsigned char **gdsp, unsigned char **bmsp, unsigned char **bdsp, long *gribrecsize);
+
+void *cgribex_handle_new_from_meassage(void *gribbuffer, size_t gribbuffersize)
+{
+  cgribex_handle *gh = (cgribex_handle*) Malloc(sizeof(cgribex_handle));
+  gh->gribbuffer = NULL;
+  gh->gribbuffersize = 0;
+  gh->pds = NULL;
+
+  if ( gribbuffersize && gribbuffer )
+    {
+      unsigned char *pds = NULL, *gds = NULL, *bms = NULL, *bds = NULL;
+      long gribrecsize;
+      int status = grib1Sections((unsigned char *)gribbuffer, (long)gribbuffersize, &pds, &gds, &bms, &bds, &gribrecsize);
+      if ( status >= 0 )
+        {
+          gh->gribbuffer = gribbuffer;
+          gh->gribbuffersize = gribbuffersize;
+          gh->pds = pds;
+          gh->gds = gds;
+          gh->bms = bms;
+          gh->bds = bds;
+        }
+    }
+
+  return (void*)gh;
+}
+
+
+void cgribex_handle_delete(void *gh)
+{
+  if ( gh ) Free(gh);
+}
+
+
+void cgribexChangeParameterIdentification(void *gh, int code, int ltype, int lev)
+{
+  if ( !gh ) return;
+
+  unsigned char *pds = ((cgribex_handle*)gh)->pds;
+  if ( !pds ) return;
+
+  pds[8]  = (unsigned char) code;
+  pds[9]  = (unsigned char) ltype;
+  pds[10] = (unsigned char) lev;
+}
+
 #endif
 /*
  * Local Variables:
diff --git a/libcdi/src/stream_cgribex.h b/libcdi/src/stream_cgribex.h
index 43f3525..34f8f33 100644
--- a/libcdi/src/stream_cgribex.h
+++ b/libcdi/src/stream_cgribex.h
@@ -12,6 +12,11 @@ size_t cgribexEncode(int memtype, int varID, int levelID, int vlistID, int gridI
 		     int vdate, int vtime, int tsteptype, int numavg,
 		     long datasize, const void *data, int nmiss, void *gribbuffer, size_t gribbuffersize);
 
+void *cgribex_handle_new_from_meassage(void *gribbuffer, size_t recsize);
+void cgribex_handle_delete(void *gh);
+
+void cgribexChangeParameterIdentification(void *gh, int code, int ltype, int lev);
+
 #endif  /* _STREAM_CGRIBEX_H */
 /*
  * Local Variables:
diff --git a/libcdi/src/stream_ext.c b/libcdi/src/stream_ext.c
index 8035949..ca94ac6 100644
--- a/libcdi/src/stream_ext.c
+++ b/libcdi/src/stream_ext.c
@@ -715,7 +715,7 @@ void extWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
   int header[4];
   header[0] = streamptr->tsteps[tsID].taxis.vdate;
   header[1] = pnum;
-  header[2] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID);
+  header[2] = (int)(zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID));
   header[3] = gridInqSize(vlistInqVarGrid(vlistID, varID));
 
   extrec_t *extp = (extrec_t*) streamptr->record->exsep;
@@ -736,7 +736,7 @@ void extWriteVarDP(stream_t *streamptr, int varID, const double *data)
   size_t nlevs    = (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
 
   for ( size_t levID = 0;  levID < nlevs; levID++ )
-    extWriteVarSliceDP(streamptr, varID, levID, &data[levID*gridsize]);
+    extWriteVarSliceDP(streamptr, varID, (int)levID, &data[levID*gridsize]);
 }
 
 #endif /* HAVE_LIBEXTRA */
diff --git a/libcdi/src/stream_grb.c b/libcdi/src/stream_grb.c
index 5d15934..c4c5c3b 100644
--- a/libcdi/src/stream_grb.c
+++ b/libcdi/src/stream_grb.c
@@ -7,9 +7,58 @@
 #include "stream_cgribex.h"
 #include "stream_grb.h"
 #include "stream_gribapi.h"
+#include "gribapi.h"
 #include "file.h"
 #include "cgribex.h"  /* gribZip gribGetZip gribGinfo */
-#include "gribapi.h"
+
+int cdiDebugExt                        =  0;      //  Debug level for the KNMI extensions
+#ifdef HIRLAM_EXTENSIONS
+// *** RELATED to GRIB only ***
+int cdiGribUseTimeRangeIndicator        = 0;       // normaly cdo looks in grib for attribute called "stepType"
+                                                   // but NWP models such as Harmonie 37h1.2, use "timeRangeIndicator"
+                                                   // where:  0: for instanteneous fields; 4: for accumulated fields
+#endif // HIRLAM_EXTENSIONS
+
+
+// Regarding operation to change parameter identification:
+// change if cdiGribChangeParameterID.active
+struct cdiGribParamChange cdiGribChangeParameterID;
+
+// Used only for CDO module Selmulti
+void streamGrbChangeParameterIdentification(int code, int ltype, int lev)
+{
+  // NOTE this is a "PROXY" function for gribapiChangeParameterIdentification();
+  // This just sets the globals. There are probably better solutions to this.
+  // The parameter change is done by function  gribapiChangeParameterIdentification() in stream_gribapi.c
+  // Setting this control variable to true will cause calling fnc. gribapiChangeParameterIdentification later.
+  // After grib attributes have been changed this variable goes to false.
+  cdiGribChangeParameterID.active = true;
+  cdiGribChangeParameterID.code = code;
+  cdiGribChangeParameterID.ltype = ltype;
+  cdiGribChangeParameterID.lev = lev;
+}
+
+struct cdiGribModeChange cdiGribChangeModeUvRelativeToGrid;
+
+// Used only for CDO module WindTrans
+void streamGrbChangeModeUvRelativeToGrid(int mode)
+{
+  cdiGribChangeModeUvRelativeToGrid.active = true;
+  cdiGribChangeModeUvRelativeToGrid.mode = (mode > 0);
+}
+
+struct cdiGribScanModeChange cdiGribDataScanningMode;
+
+void streamGrbDefDataScanningMode(int scanmode)
+{
+  cdiGribDataScanningMode.active = true;
+  cdiGribDataScanningMode.value = scanmode;
+}
+
+int  streamGrbInqDataScanningMode(void)
+{
+  return cdiGribDataScanningMode.value;
+}
 
 
 int grib1ltypeToZaxisType(int grib_ltype)
@@ -248,15 +297,11 @@ static
 int grbScanTimestep(stream_t * streamptr)
 {
   int status = CDI_EUFTYPE;
-  int filetype;
-
-  filetype  = streamptr->filetype;
+  int filetype  = streamptr->filetype;
 
 #if  defined  (HAVE_LIBCGRIBEX)
   if ( filetype == CDI_FILETYPE_GRB )
-    {
-      status = cgribexScanTimestep(streamptr);
-    }
+    status = cgribexScanTimestep(streamptr);
   else
 #endif
 #ifdef HAVE_LIBGRIB_API
@@ -272,17 +317,12 @@ int grbScanTimestep(stream_t * streamptr)
 #if  defined  (HAVE_LIBGRIB)
 int grbInqContents(stream_t * streamptr)
 {
-  int fileID;
-  int status = 0;
-
-  fileID = streamptr->fileID;
-
   streamptr->curTsID = 0;
 
-  status = grbScanTimestep1(streamptr);
-
+  int status = grbScanTimestep1(streamptr);
   if ( status == 0 && streamptr->ntsteps == -1 ) status = grbScanTimestep2(streamptr);
 
+  int fileID = streamptr->fileID;
   fileSetPos(fileID, 0, SEEK_SET);
 
   return status;
@@ -291,15 +331,13 @@ int grbInqContents(stream_t * streamptr)
 
 int grbInqTimestep(stream_t * streamptr, int tsID)
 {
-  int ntsteps, nrecs;
-
   if ( tsID == 0 && streamptr->rtsteps == 0 )
     Error("Call to cdiInqContents missing!");
 
   if ( CDI_Debug )
     Message("tsid = %d rtsteps = %d", tsID, streamptr->rtsteps);
 
-  ntsteps = CDI_UNDEFID;
+  int ntsteps = CDI_UNDEFID;
   while ( (tsID + 1) > streamptr->rtsteps && ntsteps == CDI_UNDEFID )
     {
       ntsteps = grbScanTimestep(streamptr);
@@ -310,6 +348,8 @@ int grbInqTimestep(stream_t * streamptr, int tsID)
 	}
     }
 
+  int nrecs;
+
   if ( tsID >= streamptr->ntsteps && streamptr->ntsteps != CDI_UNDEFID )
     {
       nrecs = 0;
diff --git a/libcdi/src/stream_grb.h b/libcdi/src/stream_grb.h
index a2f334f..78eb8c5 100644
--- a/libcdi/src/stream_grb.h
+++ b/libcdi/src/stream_grb.h
@@ -1,6 +1,10 @@
 #ifndef _STREAM_GRB_H
 #define _STREAM_GRB_H
 
+static inline bool gribbyte_get_bit(int number, int bit) { return (bool)((number >> (8-bit)) & 1); }
+static inline void gribbyte_set_bit(int *number, int bit) { *number |= 1 << (8-bit); }
+static inline void gribbyte_clear_bit(int *number, int bit) { *number &= ~(1 << (8-bit)); }
+
 int   grbBitsPerValue(int datatype);
 
 int   grbInqContents(stream_t *streamptr);
@@ -24,6 +28,34 @@ int   grib2ltypeToZaxisType(int grib_ltype);
 int   zaxisTypeToGrib1ltype(int zaxistype);
 int   zaxisTypeToGrib2ltype(int zaxistype);
 
+struct cdiGribParamChange
+{
+  int code, ltype, lev;
+  bool active;
+};
+
+struct cdiGribModeChange
+{
+  bool mode;
+  bool active;
+};
+
+struct cdiGribScanModeChange
+{
+  int value;
+  bool active;
+};
+
+extern struct cdiGribParamChange cdiGribChangeParameterID;
+extern struct cdiGribModeChange cdiGribChangeModeUvRelativeToGrid;
+extern struct cdiGribScanModeChange cdiGribDataScanningMode;
+
+// Used in CDO
+void streamGrbChangeParameterIdentification(int code, int ltype, int lev);
+void streamGrbChangeModeUvRelativeToGrid(int mode);
+void streamGrbDefDataScanningMode(int scanmode);
+int  streamGrbInqDataScanningMode(void);
+
 #endif  /* _STREAM_GRB_H */
 /*
  * Local Variables:
diff --git a/libcdi/src/stream_gribapi.c b/libcdi/src/stream_gribapi.c
index 79ed40b..e5de733 100644
--- a/libcdi/src/stream_gribapi.c
+++ b/libcdi/src/stream_gribapi.c
@@ -2,7 +2,7 @@
 #  include "config.h"
 #endif
 
-#if  defined  (HAVE_LIBGRIB_API)
+#ifdef HAVE_LIBGRIB_API
 #include <limits.h>
 #include <stdio.h>
 
@@ -12,6 +12,7 @@
 #include "file.h"
 #include "gribapi_utilities.h"
 #include "stream_grb.h"
+#include "stream_gribapi.h"
 #include "varscan.h"
 #include "datetime.h"
 #include "vlist.h"
@@ -35,6 +36,14 @@ typedef struct {
   int level2;
   int ltype;
   int tsteptype;
+#ifdef HIRLAM_EXTENSIONS
+    // NOTE: tsteptype MUST be part of attributes used to compare variables!
+    // Modern NWP models (HARMONIE, HIRLAM) use timeRangeIndicator to specify
+    // if the field is instantanous or accumulated.
+    // Both types are typically in the same GRIB-file.
+    // (181; 105, 0, timeRangeIndicator=0) .. instantanous rain
+    // (181; 105, 0, timeRangeIndicator=4) .. accumulated rain  .. both can be in the same grib file
+#endif // HIRLAM_EXTENSIONS
   char name[32];
 
   var_tile_t tiles;
@@ -471,12 +480,42 @@ void gribapiAddRecord(stream_t * streamptr, int param, grib_handle *gh,
       grib_get_double(gh, "latitudeOfSouthernPoleInDegrees",  &ypole);
       grib_get_double(gh, "longitudeOfSouthernPoleInDegrees", &xpole);
       grib_get_double(gh, "angleOfRotation", &angle);
-      xpole =  xpole - 180;
+      xpole -= 180;
       if ( fabs(ypole) > 0 ) ypole = -ypole; // change from south to north pole
       if ( fabs(angle) > 0 ) angle = -angle;
 
       gridDefParamRLL(gridID, xpole, ypole, angle);
     }
+  else if ( grid->projtype == CDI_PROJ_LCC )
+    {
+      double a = 6367470., rf = 0;
+      long earthIsOblate;
+      grib_get_long(gh, "earthIsOblate", &earthIsOblate);
+      if ( earthIsOblate ) { a = 6378160.; rf = 297.0; }
+      double lon_0, lat_1, lat_2, xval_0, yval_0;
+      long projflag = 0;
+      grib_get_double(gh, "longitudeOfFirstGridPointInDegrees", &xval_0);
+      grib_get_double(gh, "latitudeOfFirstGridPointInDegrees", &yval_0);
+      grib_get_double(gh, "LoVInDegrees", &lon_0);
+      grib_get_double(gh, "Latin1InDegrees", &lat_1);
+      grib_get_double(gh, "Latin2InDegrees", &lat_2);
+      grib_get_long(gh, "projectionCentreFlag", &projflag);
+      bool lsouth = gribbyte_get_bit(projflag, 1);
+      if ( lsouth ) { lat_1 = -lat_1; lat_2 = -lat_2; }
+
+      double lat_0 = lat_2;
+      double x_0 = grid_missval;
+      double y_0 = grid_missval;
+
+      if ( proj_lonlat_to_lcc_func )
+        {
+          x_0 = xval_0; y_0 = yval_0;
+          proj_lonlat_to_lcc_func(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, (size_t)1, &x_0, &y_0);
+          if ( IS_NOT_EQUAL(x_0, grid_missval) && IS_NOT_EQUAL(y_0, grid_missval) )
+            { x_0 = -x_0; y_0 = -y_0; }
+        }
+      gridDefParamLCC(gridID, grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0);
+    }
 
   int zaxistype = gribapiGetZaxisType(gribEditionNumber(gh), leveltype1);
 
@@ -1669,6 +1708,8 @@ void gribapiDefStepUnits(int editionNumber, grib_handle *gh, int timeunit, int p
         }
       else
         {
+	  // NOTE KNMI:  HIRLAM model files LAMH_D11 are in grib1 and do NOT have key indicatorOfUnitForTimeRange
+	  // Watch out for compatibility issues.
           GRIB_CHECK(my_grib_set_long(gh, "indicatorOfUnitOfTimeRange", unitsOfTime), 0);
         }
     }
@@ -1760,7 +1801,7 @@ int gribapiDefDateTimeRel(int editionNumber, grib_handle *gh, int rdate, int rti
 
   int factor = getTimeunitFactor(timeunit);
 
-  if ( !(int) fmod(days*86400.0 + secs, factor) )
+  if ( !(int)(fmod(days*86400.0 + secs, factor)))
     {
       int proDefTempNum = gribapiDefSteptype(editionNumber, gh, productDefinitionTemplate, typeOfGeneratingProcess, tsteptype, gcinit);
 
@@ -1927,10 +1968,17 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
         }
     }
 
-  if ( gridtype == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+  if ( gridtype == GRID_PROJECTION )
     {
-      gridtype = GRID_LONLAT;
-      lrotated = true;
+      if ( gridInqProjType(gridID) == CDI_PROJ_RLL )
+        {
+          gridtype = GRID_LONLAT;
+          lrotated = true;
+        }
+      else if ( gridInqProjType(gridID) == CDI_PROJ_LCC )
+        {
+          gridtype = GRID_LCC;
+        }
     }
 
   if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
@@ -1957,7 +2005,6 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
       {
 	double xfirst = 0, xlast = 0, xinc = 0;
 	double yfirst = 0, ylast = 0, yinc = 0;
-	double latIncr;
 
         const char *mesg;
         size_t len;
@@ -1987,8 +2034,8 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
           }
         GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
 
-	long nlon = gridInqXsize(gridID);
-	long nlat = gridInqYsize(gridID);
+	int nlon = gridInqXsize(gridID);
+	int nlat = gridInqYsize(gridID);
 
 	if ( gridtype == GRID_GAUSSIAN_REDUCED )
 	  {
@@ -1999,14 +2046,14 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	    gridInqRowlon(gridID, rowlon);
 	    for ( int i = 0; i < nlat; ++i ) pl[i] = rowlon[i];
 
-            GRIB_CHECK(grib_set_long_array(gh, "pl", pl, nlat), 0);
+            GRIB_CHECK(grib_set_long_array(gh, "pl", pl, (size_t)nlat), 0);
 
 	    Free(pl);
 	    Free(rowlon);
 
 	    xfirst = 0;
-	    xlast  = 360.-360./(nlat*2);
-	    xinc   = 360./(nlat*2);
+	    xinc   =        360. * 0.5 / (double)nlat;
+	    xlast  = 360. - 360. * 0.5 / (double)nlat;
 	  }
 	else
 	  {
@@ -2015,7 +2062,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	      {
 		xfirst = gridInqXval(gridID, 0);
                 xlast  = gridInqXval(gridID, (lcurvi ? nlon*nlat : nlon) - 1);
-		xinc   = gridInqXinc(gridID);
+		xinc   = fabs(gridInqXinc(gridID));
 	      }
 	  }
 
@@ -2024,7 +2071,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	  {
 	    yfirst = gridInqYval(gridID, 0);
             ylast  = gridInqYval(gridID, (lcurvi ? nlon*nlat : nlat) - 1);
-	    yinc   = gridInqYinc(gridID);
+	    yinc   = fabs(gridInqYinc(gridID));
 	  }
 
 	if ( gridtype != GRID_GAUSSIAN_REDUCED ) GRIB_CHECK(my_grib_set_long(gh, "Ni", nlon), 0);
@@ -2037,8 +2084,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
 	GRIB_CHECK(my_grib_set_double(gh, "latitudeOfLastGridPointInDegrees",   ylast), 0);
 
         {
-          long jscan = 0;
-          if ( yfirst < ylast ) jscan = 1;
+          long iscan = xfirst > xlast;
+          GRIB_CHECK(my_grib_set_long(gh, "iScansNegatively", iscan), 0);
+        }
+        {
+          long jscan = yfirst < ylast;
           GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jscan), 0);
         }
 
@@ -2050,9 +2100,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
           }
 	else
 	  {
-	    latIncr = yinc;
-	    if ( latIncr < 0 ) latIncr = -latIncr;
-	    GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", latIncr), 0);
+	    GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", yinc), 0);
 	  }
 
 	if ( lrotated )
@@ -2060,7 +2108,7 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
             double xpole = 0, ypole = 0, angle = 0;
             gridInqParamRLL(gridID, &xpole, &ypole, &angle);
 
-            xpole =  xpole + 180;
+            xpole += 180;
             if ( fabs(ypole) > 0 ) ypole = -ypole; // change from north to south pole
             if ( fabs(angle) > 0 ) angle = -angle;
             GRIB_CHECK(my_grib_set_double(gh, "latitudeOfSouthernPoleInDegrees",  ypole), 0);
@@ -2086,55 +2134,69 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
         if ( lieee )
           GRIB_CHECK(my_grib_set_long(gh, "precision", datatype == CDI_DATATYPE_FLT64 ? 2 : 1), 0);
 
+        long uvRelativeToGrid = gridInqUvRelativeToGrid(gridID);
+        if ( uvRelativeToGrid ) GRIB_CHECK(my_grib_set_long(gh, "uvRelativeToGrid", uvRelativeToGrid), 0);
+
 	break;
       }
     case GRID_LCC:
       {
-	double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
-	int projflag, scanflag;
-
 	int xsize = gridInqXsize(gridID);
 	int ysize = gridInqYsize(gridID);
 
-	gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                        &projflag, &scanflag);
+        double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+	gridInqParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+	gridVerifyGribParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+        if ( xval_0 < 0 ) xval_0 += 360;
+        bool lsouth = (lat_1 < 0);
+        if ( lsouth ) { lat_1 = -lat_2; lat_2 = -lat_2; }
+        int projflag = 0;
+        if ( lsouth ) gribbyte_set_bit(&projflag, 1);
+
+        double xinc = gridInqXinc(gridID);
+        double yinc = gridInqYinc(gridID);
 
         static const char mesg[] = "lambert";
-        size_t len = sizeof (mesg) -1;
+        size_t len = sizeof(mesg) -1;
         GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
 
 	GRIB_CHECK(my_grib_set_long(gh, "Nx", xsize), 0);
 	GRIB_CHECK(my_grib_set_long(gh, "Ny", ysize), 0);
-
-        /* FIXME: lround should probably be round here */
-	GRIB_CHECK(my_grib_set_double(gh, "DxInMetres", (double)lround(xincm)), 0);
-        /* FIXME: lround should probably be round here */
-	GRIB_CHECK(my_grib_set_double(gh, "DyInMetres", (double)lround(yincm)), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", originLon), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", originLat), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "LoVInDegrees", lonParY), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "Latin1InDegrees", lat1), 0);
-	GRIB_CHECK(my_grib_set_double(gh, "Latin2InDegrees", lat2), 0);
-
+	GRIB_CHECK(my_grib_set_long(gh, "DxInMetres", lround(xinc)), 0);
+	GRIB_CHECK(my_grib_set_long(gh, "DyInMetres", lround(yinc)), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "longitudeOfFirstGridPointInDegrees", xval_0), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", yval_0), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "LoVInDegrees", lon_0), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "Latin1InDegrees", lat_1), 0);
+	GRIB_CHECK(my_grib_set_double(gh, "Latin2InDegrees", lat_2), 0);
+        GRIB_CHECK(my_grib_set_long(gh, "projectionCentreFlag", projflag), 0);
+
+        long uvRelativeToGrid = gridInqUvRelativeToGrid(gridID);
+        if ( uvRelativeToGrid ) GRIB_CHECK(my_grib_set_long(gh, "uvRelativeToGrid", uvRelativeToGrid), 0);
+        long earthIsOblate = (IS_EQUAL(a, 6378160.) && IS_EQUAL(rf, 297.));
+        if ( earthIsOblate ) GRIB_CHECK(my_grib_set_long(gh, "earthIsOblate", earthIsOblate), 0);
+
+        int scanflag = 0;
+        gribbyte_set_bit(&scanflag, 2);
         if ( editionNumber <= 1 )
-          {
-            GRIB_CHECK(my_grib_set_long(gh, "projectionCenterFlag", projflag), 0);
-            GRIB_CHECK(my_grib_set_long(gh, "scanningMode", scanflag), 0);
-          }
+          GRIB_CHECK(my_grib_set_long(gh, "scanningMode", (long)scanflag), 0);
 
 	break;
       }
     case GRID_SPECTRAL:
       {
-        static const char mesg[] = "sh";
-        size_t len = sizeof (mesg) -1;
-	GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
-
-	int trunc = gridInqTrunc(gridID);
-	GRIB_CHECK(my_grib_set_long(gh, "J", trunc), 0);
-	GRIB_CHECK(my_grib_set_long(gh, "K", trunc), 0);
-	GRIB_CHECK(my_grib_set_long(gh, "M", trunc), 0);
-
+        {
+          static const char mesg[] = "sh";
+          size_t len = sizeof (mesg) -1;
+          GRIB_CHECK(my_grib_set_string(gh, "gridType", mesg, &len), 0);
+        }
+	{
+          int trunc = gridInqTrunc(gridID);
+          enum { numTruncAtt = 3 };
+          static const char truncAttNames[numTruncAtt][2] = { "J", "K", "M" };
+          for (size_t i = 0; i < numTruncAtt; ++i)
+            GRIB_CHECK(my_grib_set_long(gh, truncAttNames[i], trunc), 0);
+        }
 	// GRIB_CHECK(my_grib_set_long(gh, "numberOfDataPoints", gridsize), 0);
         /*
         if ( lieee )
@@ -2151,10 +2213,11 @@ void gribapiDefGrid(int editionNumber, grib_handle *gh, int gridID, int comptype
             static const char mesg[] = "spectral_complex";
             size_t len = sizeof (mesg) -1;
 	    GRIB_CHECK(my_grib_set_string(gh, "packingType", mesg, &len), 0);
-
-	    GRIB_CHECK(my_grib_set_long(gh, "JS", 20), 0);
-	    GRIB_CHECK(my_grib_set_long(gh, "KS", 20), 0);
-	    GRIB_CHECK(my_grib_set_long(gh, "MS", 20), 0);
+            enum { numTruncAtt = 3 };
+            static const char truncAttNames[numTruncAtt][3]
+              = { "JS", "KS", "MS" };
+            for (size_t i = 0; i < numTruncAtt; ++i)
+              GRIB_CHECK(my_grib_set_long(gh, truncAttNames[i], 20), 0);
 	  }
 	else
 	  {
@@ -2238,16 +2301,14 @@ static
 void getLevelFactor(double level, long *factor, long *out_scaled_value)
 {
   double scaled_value  = level;
-  /* FIXME: lround might be better here */
-  long   iscaled_value = (long) round(scaled_value);
+  long   iscaled_value = lround(scaled_value);
   long   i;
 
   const double eps = 1.e-8;
   for ( i=0; (fabs(scaled_value - (double) iscaled_value) >= eps) && i < 7; i++ )
     {
       scaled_value *= 10.;
-      /* FIXME: lround might be better here */
-      iscaled_value = (long)round(scaled_value);
+      iscaled_value = lround(scaled_value);
     }
 
   (*factor)           = i;
@@ -2552,6 +2613,427 @@ void gribapiDefLevel(int editionNumber, grib_handle *gh, int zaxisID, int levelI
     }
 }
 
+
+int gribapiGetScanningMode(grib_handle *gh)
+{
+  long iScansNegatively;
+  long jScansPositively;
+  long jPointsAreConsecutive;
+
+  GRIB_CHECK(grib_get_long(gh, "iScansNegatively", &iScansNegatively), 0);
+  GRIB_CHECK(grib_get_long(gh, "jScansPositively", &jScansPositively), 0);
+  GRIB_CHECK(grib_get_long(gh, "jPointsAreConsecutive", &jPointsAreConsecutive), 0);
+  int scanningMode
+    = 128*(bool)iScansNegatively
+    + 64 *(bool)jScansPositively
+    + 32 *(bool)jPointsAreConsecutive;
+  if (cdiDebugExt>=30)
+    printf("gribapiGetScanningMode(): Scanning mode = %02d (%1d%1d%1d)*32; \n",\
+            scanningMode,(int)jPointsAreConsecutive,(int)jScansPositively,(int)iScansNegatively);
+
+ return scanningMode;
+}
+
+
+void gribapiSetScanningMode(grib_handle *gh, int scanningMode)
+{
+   // 127: reserved for testing; generated test data will be in 64 scanning mode
+  //if (scanningMode== 127)  scanningMode = 64;
+
+  long iScansNegatively      = (scanningMode & 128)/128;
+  long jScansPositively      = (scanningMode & 64)/64;
+  long jPointsAreConsecutive = (scanningMode & 32)/32;
+
+  if (cdiDebugExt>=30)
+  {
+    long paramId, levelTypeId, levelId, uvRelativeToGrid;
+    GRIB_CHECK(grib_get_long(gh, "uvRelativeToGrid", &uvRelativeToGrid), 0);
+    GRIB_CHECK(grib_get_long(gh, "indicatorOfParameter", &paramId), 0);
+    GRIB_CHECK(grib_get_long(gh, "indicatorOfTypeOfLevel", &levelTypeId), 0);
+    GRIB_CHECK(grib_get_long(gh, "level", &levelId), 0);
+    printf("gribapiSetScanningMode(): (param,ltype,level) = (%3d,%3d,%4d); Scanning mode = %02d (%1d%1d%1d)*32;  uvRelativeToGrid = %02d\n",\
+            (int)paramId, (int)levelTypeId, (int)levelId,
+            scanningMode,(int)jPointsAreConsecutive,(int)jScansPositively,(int)iScansNegatively,
+            (int)uvRelativeToGrid);
+  }
+
+  GRIB_CHECK(my_grib_set_long(gh, "iScansNegatively", iScansNegatively), 0);
+  GRIB_CHECK(my_grib_set_long(gh, "jScansPositively", jScansPositively), 0);
+  GRIB_CHECK(my_grib_set_long(gh, "jPointsAreConsecutive", jPointsAreConsecutive), 0);
+}
+
+
+static void gribapiSetUvRelativeToGrid(grib_handle *gh, int mode)
+{
+  long uvRelativeToGridMode = mode;
+  long uvRelativeToGridModeOld;
+
+  GRIB_CHECK(grib_get_long(gh, "uvRelativeToGrid", &uvRelativeToGridModeOld), 0);
+
+  if (cdiDebugExt>=30)
+    printf("gribapiSetUvRelativeToGrid():  uvRelativeToGrid: %02d (old) => %02d (new); \n",(int)uvRelativeToGridModeOld,(int)uvRelativeToGridMode);
+
+  GRIB_CHECK(my_grib_set_long(gh, "uvRelativeToGrid", uvRelativeToGridMode), 0);
+}
+
+
+  /*
+    TABLE 8. SCANNING MODE FLAG
+
+    (GDS Octet 28)
+    BIT     VALUE     MEANING
+    1       0       Points scan in +i direction
+            1       Points scan in -i direction
+    2       0       Points scan in -j direction
+            1       Points scan in +j direction
+    3       0       Adjacent points in i direction are consecutive
+                      (FORTRAN: (I,J))
+            1       Adjacent points in j direction are consecutive
+                    (FORTRAN: (J,I))
+
+    => Scanning Mode     0 0 0 0 0 0 0 0  (00 dec)  +i, -j; i direction consecutive (row-major    order West->East   & North->South)
+    => Scanning Mode     0 1 0 0 0 0 0 0  (64 dec)  +i, +j; i direction consecutive (row-major    order West->East   & South->North )
+    => Scanning Mode     1 1 0 0 0 0 0 0  (96 dec)  +i, +j; j direction consecutive (column-major order South->North & West->East )
+
+    NOTE:  South->North  - As if you would plot the data as image on the screen
+                           where [0,0] of the data is the top-left pixel.
+
+                           grib2ppm LAMH_D11_201302150000_00000_oro | display ppm:-
+                           ImageMagick (display): [0,0] of an image belongs to the top-left pixel
+    [DEFAULT] : 64 dec
+
+    iScansNegatively = 0;
+    jScansPositively = 1;
+    jPointsAreConsecutive = 0;    => Scanning Mode 64
+
+    cdo selindexbox,1,726,100,550 LAMH_D11_201302150000_00000_oro LAMH_D11_201302150000_00000_oro_cropped
+    grib2ppm LAMH_D11_201302150000_00000_oro_cropped | /usr/bin/display ppm:- &
+    # ^^^ this image will be missing the souther parts of data
+
+    grib2ppm LAMH_D11_201302150000_00000_oro | /usr/bin/display ppm:- &
+    # ^ full domain data
+  */
+
+#ifdef HIRLAM_EXTENSIONS
+static void
+verticallyFlipGridDefinitionWhenScanningModeChanged(grib_handle *gh, double yfirst, double ylast, double yinc )
+{
+  /*
+  Nj = 550;
+  latitudeOfFirstGridPointInDegrees = -30.8;
+  latitudeOfLastGridPointInDegrees = 24.1;
+  iScansNegatively = 0;
+  jScansPositively = 0;
+  jPointsAreConsecutive = 0;
+  jDirectionIncrementInDegrees = 0.1;
+
+  When switching from scanning mode 0 <=> 64
+  yfirst = -30.8 + (550-1)*0.1
+
+  yfirst = yfirst + (ysize-1) * yinc
+  yinc   = -1.0*yinc
+
+  */
+
+
+  //long jDim=0;
+  //GRIB_CHECK(grib_get_long(gh, "Nj", &jDim), 0);
+
+  double latitudeOfFirstGridPointInDegrees;
+  double latitudeOfLastGridPointInDegrees;
+  double jDirectionIncrementInDegrees;
+
+  //GRIB_CHECK(grib_get_double(gh, "latitudeOfFirstGridPointInDegrees", &latitudeOfFirstGridPointInDegrees), 0);  // yfirst
+  //GRIB_CHECK(grib_get_double(gh, "latitudeOfLastGridPointInDegrees", &latitudeOfLastGridPointInDegrees), 0);    // ylast
+  //GRIB_CHECK(grib_get_double(gh, "jDirectionIncrementInDegrees", &jDirectionIncrementInDegrees), 0);  // yinc
+
+  if (cdiDebugExt>=10)
+  {
+      Message(" BEFORE: yfirst = %f; ylast = %f; yinc = %f; ", yfirst,ylast, yinc);
+  }
+
+  GRIB_CHECK(my_grib_set_double(gh, "latitudeOfFirstGridPointInDegrees", ylast), 0);
+  GRIB_CHECK(my_grib_set_double(gh, "latitudeOfLastGridPointInDegrees", yfirst), 0);
+  //yinc *= -1.0; // don't set yinc here ...
+  //GRIB_CHECK(my_grib_set_double(gh, "jDirectionIncrementInDegrees", yinc), 0);
+
+  if (cdiDebugExt>=10)
+  {
+    GRIB_CHECK(grib_get_double(gh, "latitudeOfFirstGridPointInDegrees", &latitudeOfFirstGridPointInDegrees), 0);  // yfirst
+    GRIB_CHECK(grib_get_double(gh, "latitudeOfLastGridPointInDegrees", &latitudeOfLastGridPointInDegrees), 0);    // ylast
+    GRIB_CHECK(grib_get_double(gh, "jDirectionIncrementInDegrees", &jDirectionIncrementInDegrees), 0);  // yinc
+    Message("CHANGED INTO:  yfirst = %f, ylast = %f, yinc = %f",latitudeOfFirstGridPointInDegrees,latitudeOfLastGridPointInDegrees, jDirectionIncrementInDegrees);
+  }
+}
+
+static void
+convertDataScanningMode(int scanModeIN, int scanModeOUT, double *data,
+                        int gridsize, int iDim, int jDim)
+{
+  int i,j;
+  int idxIN, idxOUT;
+
+   // 127: reserved for testing; it will generate test data in 64 scanning mode
+  if (scanModeOUT== 127)  // fill with testdata ...
+  {
+      scanModeOUT = 64;
+      if (cdiDebugExt>=30) printf("convertDataScanningMode(): Generating test data in 64 scanning mode..\n");
+      for (j=0; j<jDim; j++)
+      {
+        int jXiDim = j*iDim;
+        for (i=0; i<iDim; i++)
+        {
+          idxIN = i + jXiDim;
+          data[idxIN] = (double) (100.0*j +i);
+        }
+      }
+  }
+
+  if ( (iDim*jDim)!= gridsize)
+  {
+    if (cdiDebugExt>=30) printf("convertDataScanningMode(): ERROR: (iDim*jDim)!= gridsize;  (%d * %d) != %d\n", iDim,jDim, gridsize);
+    return;
+  }
+  if (cdiDebugExt>=30) printf("convertDataScanningMode(): scanModeIN=%02d => scanModeOUT=%02d ; where: (iDim * jDim == gridsize)  (%d*%d == %d)\n",scanModeIN, scanModeOUT, iDim,jDim, gridsize);
+
+  if (cdiDebugExt>=100)
+  {
+      printf("convertDataScanningMode(): data IN:\n");
+      for (j=0; j<jDim; j++)
+      {
+        int jXiDim = j*iDim;
+        for (i=0; i<iDim; i++)
+        {
+          idxIN = i + jXiDim;
+          printf("%03.0f, ",data[idxIN]);
+        }
+        printf("\n");
+      }
+  }
+
+  if (scanModeIN==scanModeOUT)
+  {
+    if (cdiDebugExt>=30) printf("convertDataScanningMode(): INFO: Nothing to do;  scanModeIN==scanModeOUT..\n");
+    return;
+  }
+
+  if (0)
+  {
+      return;
+      if (scanModeOUT==00)
+      {
+          if (cdiDebugExt>0) printf("convertDataScanningMode(): Leave data unchaged BUT set scanModeOUT=00.\n");
+          // CHECK:  Looks like that GRIB-API provide (no matter what) data in the scannning mode 00, even it is store in the gribfile as 64 !!
+          return;
+      }
+  }
+  double *dataCopy = NULL;
+  dataCopy = (double *) malloc(gridsize*sizeof(double));
+
+  memcpy((void*)dataCopy,(void*) data, gridsize*sizeof(double));
+
+  if (scanModeIN==64)           // Scanning Mode (00 dec)  +i, -j; i direction consecutive (row-major    order West->East   & South->North )
+  {                             // Scanning Mode (64 dec)  +i, +j; i direction consecutive (row-major    order West->East   & North->South )
+                                // Scanning Mode (96 dec)  +i, +j; j direction consecutive (column-major order North->South & West->East )
+      if (scanModeOUT==00)
+      // CHECK:  Looks like that GRIB-API provide (no matter what) data in the scannning mode 00, even it is store in the gribfile as 64 !!
+#define VERTICAL_FLIP
+#ifdef VERTICAL_FLIP
+      { // flip the data vertically ..
+        idxIN= 0; idxOUT= (jDim-1)*iDim;
+        if (cdiDebugExt>=30) printf("convertDataScanningMode():  copying rows nr. (%04d : %04d)\n",0,jDim-1);
+        for (j=0; j<jDim; j++)
+        {
+          memcpy((void*)&data[idxOUT], (void*)&dataCopy[idxIN], iDim*sizeof(double));
+          idxIN  += iDim; idxOUT -= iDim;
+        }
+      } // end if (scanModeOUT==00)*/
+#endif
+#ifdef HORIZONTAL_FLIP
+      { // flip data horizontally ...
+        if (1)
+        {
+            if (cdiDebugExt>=30) printf("convertDataScanningMode():  copying columns nr. (%04d : %04d);\n", 0, iDim-1);
+            for (i=0; i<iDim; i++)
+            {
+              for (j=0; j<jDim; j++)
+              {
+                int jXiDim = j*iDim;
+                idxIN  = i           + jXiDim;
+                //data[idxIN] = (double) (100.0*j +i);  // just some testdata ..
+                idxOUT = iDim - i -1 + jXiDim;
+                //printf("[%03d=>%03d] = %f;",idxIN,idxOUT,dataCopy[idxIN]);
+                data[idxOUT] =  dataCopy[idxIN];
+              }
+            }
+        }
+      } // end if (scanModeOUT==00)
+#endif
+
+      if (scanModeOUT==96)
+      { // transpose the data
+        if (cdiDebugExt>=30) printf("convertDataScanningMode():  transpose data rows=>columns nr. (%04d : %04d) => (%04d : %04d);\n", 0, iDim-1, 0, jDim-1);
+        for (j=0; j<jDim; j++)
+        {
+          int jXiDim = j*iDim;
+          for (i=0; i<iDim; i++)
+          {
+            idxIN  = i + jXiDim;
+            idxOUT = j + i*jDim;
+            //printf("[%03d=>%03d] = %f;",idxIN,idxOUT,dataCopy[idxIN]);
+            data[idxOUT] =  dataCopy[idxIN];
+          }
+          //printf(".\n");
+        }
+      } // end if (scanModeOUT==96)
+  } // end if (scanModeIN==64)
+
+  if (scanModeIN==00)           // Scanning Mode (00 dec)  +i, -j; i direction consecutive (row-major    order West->East   & South->North )
+  {                             // Scanning Mode (64 dec)  +i, +j; i direction consecutive (row-major    order West->East   & North->South )
+                               // Scanning Mode (96 dec)  +i, +j; j direction consecutive (column-major order North->South & West->East )
+    if (scanModeOUT==64)
+      { // flip the data vertically ..
+        idxIN= 0; idxOUT= (jDim-1)*iDim;
+        for (j=0; j<jDim; j++)
+        {
+          if (cdiDebugExt>=25) printf("convertDataScanningMode():  copying row nr. %04d; [idxIN=%08d] => [idxOUT=%08d]\n",j, idxIN, idxOUT);
+          memcpy((void*)&data[idxOUT], (void*)&dataCopy[idxIN], iDim*sizeof(double));
+          idxIN  += iDim; idxOUT -= iDim;
+        }
+      } // end if (scanModeOUT==64)
+
+      if (scanModeOUT==96)
+      { // transpose the data
+        int jInv;
+        for (j=0; j<jDim; j++)
+        {
+          if (cdiDebugExt>=30) printf("convertDataScanningMode():  processing row nr. %04d;\n", j);
+          jInv = (jDim-1) -j;
+          for (i=0; i<iDim; i++)
+            data[j + i*jDim] =  dataCopy[i + jInv*iDim];  // source data has -j
+        }
+      } // end if (scanModeOUT==96)
+  } // end if (scanModeIN==00)
+
+  if (scanModeIN==96)           // Scanning Mode (00 dec)  +i, -j; i direction consecutive (row-major    order West->East   & South->North )
+  {                             // Scanning Mode (64 dec)  +i, +j; i direction consecutive (row-major    order West->East   & North->South )
+                                // Scanning Mode (96 dec)  +i, +j; j direction consecutive (column-major order North->South & West->East )
+    if (scanModeOUT==64)
+      { // transpose the data
+        for (j=0; j<jDim; j++)
+        {
+          if (cdiDebugExt>=30) printf("convertDataScanningMode():  processing row nr. %04d;\n", j);
+          int jXiDim = j*iDim;
+          for (i=0; i<iDim; i++)
+            //data[j + i*jDim] =  dataCopy[i + j*iDim];
+            data[i + jXiDim] =  dataCopy[j + i*jDim];
+        }
+      } // end if (scanModeOUT==64)
+
+      if (scanModeOUT==00)
+      { // transpose the data
+        idxIN= 0; idxOUT= 0;
+        int jInv;
+        for (j=0; j<jDim; j++)
+        {
+          if (cdiDebugExt>=30) printf("convertDataScanningMode():  processing row nr. %04d;\n", j);
+          jInv = (jDim-1) -j;
+          int jXiDim = j*iDim;
+          for (i=0; i<iDim; i++)
+            //data[jInv + iXjDim] =  dataCopy[i + jXiDim];  // target data has -j
+            data[i + jXiDim] =  dataCopy[jInv + i*jDim];  // target data has -j
+        }
+      } // end if (scanModeOUT==00)
+  } // end if (scanModeIN==96)
+
+  if (cdiDebugExt>=100)
+  {
+      printf("convertDataScanningMode(): data OUT (new scanning mode):\n");
+      for (j=0; j<jDim; j++)
+      {
+        int jXiDim = j*iDim;
+        for (i=0; i<iDim; i++)
+        {
+          idxIN = i + jXiDim;
+          printf("%03.0f, ",data[idxIN]);
+        }
+        printf("\n");
+      }
+  }
+
+  free(dataCopy); return;
+}
+#endif //HIRLAM_EXTENSIONS
+
+static
+void gribapiSetExtMode(grib_handle *gh, int gridID, long datasize, const double *data)
+{
+  /*
+  Nj = 550;
+  latitudeOfFirstGridPointInDegrees = -30.8;
+  latitudeOfLastGridPointInDegrees = 24.1;
+  iScansNegatively = 0;
+  jScansPositively = 0;
+  jPointsAreConsecutive = 0;
+  jDirectionIncrementInDegrees = 0.1; */
+#ifndef HIRLAM_EXTENSIONS
+  (void)data;
+  (void)datasize;
+#endif
+  int gridtype = gridInqType(gridID);
+  if ( gridtype == GRID_GENERIC || gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN ||
+       gridtype == GRID_GAUSSIAN_REDUCED || gridtype == GRID_PROJECTION )
+    {
+#ifdef HIRLAM_EXTENSIONS
+      int scanModeIN = gridInqScanningMode(gridID);
+
+      if (cdiDebugExt>=100)
+        {
+          int gridsize = gridInqSize(gridID);
+          Message("(scanModeIN=%d; gridsize=%d", scanModeIN, gridsize);
+        }
+
+      if ( cdiGribDataScanningMode.active )   // allowed modes: <0, 64, 96>; Default is 64
+        {
+          int iDim = gridInqXsize(gridID);
+          int jDim = gridInqYsize(gridID);
+
+          double yfirst = gridInqYval(gridID,      0);
+          double ylast  = gridInqYval(gridID, jDim-1);
+          double yinc   = gridInqYinc(gridID);
+
+          int scanModeOUT = cdiGribDataScanningMode.value;
+          convertDataScanningMode(scanModeIN, scanModeOUT, (double*)data, datasize, iDim, jDim);
+          // This will overrule the old scanning mode of the given grid
+          if (cdiDebugExt>=10) Message("Set GribDataScanningMode (%d) => (%d)", scanModeIN, cdiGribDataScanningMode.value);
+          gribapiSetScanningMode(gh, cdiGribDataScanningMode.value);
+
+          if (((scanModeIN==00) && (cdiGribDataScanningMode.value==64)) ||
+              ((scanModeIN==64) && (cdiGribDataScanningMode.value==00)) )
+            verticallyFlipGridDefinitionWhenScanningModeChanged(gh, yfirst, ylast, yinc);
+        }
+      else
+        {
+          if (cdiDebugExt>=100) Message("Set GribDataScanningMode => (%d) based on used grid", scanModeIN);
+          gribapiSetScanningMode(gh, scanModeIN);
+        }
+#endif
+
+      if ( cdiGribChangeModeUvRelativeToGrid.active )
+        {
+          // this will overrule/change the UvRelativeToGrid flag;
+          // typically when the wind is rotated with respect to north pole
+          if (cdiDebugExt>=100) Message("Set ModeUvRelativeToGrid =>%d ( note grid has: %d)", cdiGribChangeModeUvRelativeToGrid.mode, gridInqUvRelativeToGrid(gridID));
+          GRIB_CHECK(my_grib_set_long(gh, "uvRelativeToGrid", (long) cdiGribChangeModeUvRelativeToGrid.mode), 0);
+        }
+      else
+        {
+          if (cdiDebugExt>=100) Message("Set ModeUvRelativeToGrid =>%d based on used grid", gridInqUvRelativeToGrid(gridID));
+          gribapiSetUvRelativeToGrid(gh, gridInqUvRelativeToGrid(gridID));
+        }
+    }
+}
+
 /* #define GRIBAPIENCODETEST 1 */
 
 size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisID,
@@ -2605,7 +3087,8 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
     }
   */
 
-  gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess, gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
+  gribapiDefTime((int)editionNumber, productDefinitionTemplate, typeOfGeneratingProcess,
+                 gh, vdate, vtime, tsteptype, numavg, vlistInqTaxis(vlistID), gc->init);
 
   if ( ! gc->init ) gribapiDefInstitut(gh, vlistID, varID);
   if ( ! gc->init ) gribapiDefModel(gh, vlistID, varID);
@@ -2671,6 +3154,8 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
       GRIB_CHECK(my_grib_set_double(gh, "missingValue", vlistInqVarMissval(vlistID, varID)), 0);
     }
 
+  gribapiSetExtMode(gh, gridID, datasize, data);
+
   GRIB_CHECK(grib_set_double_array(gh, "values", data, (size_t)datasize), 0);
 
   /* get the size of coded message  */
@@ -2690,6 +3175,20 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 
   return recsize;
 }
+
+
+void gribapiChangeParameterIdentification(grib_handle *gh, int code, int ltype, int lev)
+{
+  long  indicatorOfParameter,  indicatorOfTypeOfLevel,  level; //  timeRangeIndicator: could be included later
+  indicatorOfParameter = code;
+  indicatorOfTypeOfLevel = ltype;
+  level = lev;
+
+  if (indicatorOfParameter!=-1) GRIB_CHECK(my_grib_set_long(gh, "indicatorOfParameter", indicatorOfParameter), 0);
+  if (indicatorOfTypeOfLevel!=-1) GRIB_CHECK(my_grib_set_long(gh, "indicatorOfTypeOfLevel", indicatorOfTypeOfLevel), 0);
+  if (level!=-1) GRIB_CHECK(my_grib_set_long(gh, "level", level), 0);
+}
+
 #endif
 
 /*
diff --git a/libcdi/src/stream_gribapi.h b/libcdi/src/stream_gribapi.h
index ac4755b..9b4e980 100644
--- a/libcdi/src/stream_gribapi.h
+++ b/libcdi/src/stream_gribapi.h
@@ -1,6 +1,10 @@
 #ifndef _STREAM_GRIBAPI_H
 #define _STREAM_GRIBAPI_H
 
+#ifdef HAVE_LIBGRIB_API
+
+#include "gribapi.h"
+
 int gribapiScanTimestep1(stream_t * streamptr);
 int gribapiScanTimestep2(stream_t * streamptr);
 int gribapiScanTimestep(stream_t * streamptr);
@@ -13,6 +17,13 @@ size_t gribapiEncode(int varID, int levelID, int vlistID, int gridID, int zaxisI
 		     long datasize, const double *data, int nmiss, void **gribbuffer, size_t *gribbuffersize,
 		     int ljpeg, void *gribContainer);
 
+int gribapiGetScanningMode(grib_handle *gh);
+void gribapiSetScanningMode(grib_handle *gh, int scanningMode);
+
+void gribapiChangeParameterIdentification(grib_handle *gh, int code, int ltype, int lev);
+
+#endif
+
 #endif  /* _STREAM_GRIBAPI_H */
 /*
  * Local Variables:
diff --git a/libcdi/src/stream_history.c b/libcdi/src/stream_history.c
index ff2ef1b..0ac5400 100644
--- a/libcdi/src/stream_history.c
+++ b/libcdi/src/stream_history.c
@@ -7,16 +7,22 @@
 #include "cdi_int.h"
 #include "stream_cdf.h"
 
+static inline bool
+filetypeIsNetCDF(int filetype)
+{
+  return filetype == CDI_FILETYPE_NC
+    ||   filetype == CDI_FILETYPE_NC2
+    ||   filetype == CDI_FILETYPE_NC4
+    ||   filetype == CDI_FILETYPE_NC4C;
+}
+
 
 void streamDefHistory(int streamID, int length, const char *history)
 {
 #ifdef HAVE_LIBNETCDF
   stream_t *streamptr = stream_to_pointer(streamID);
 
-  if ( streamptr->filetype == CDI_FILETYPE_NC  ||
-       streamptr->filetype == CDI_FILETYPE_NC2 ||
-       streamptr->filetype == CDI_FILETYPE_NC4 ||
-       streamptr->filetype == CDI_FILETYPE_NC4C )
+  if ( filetypeIsNetCDF(streamptr->filetype) )
     {
       char *histstring;
       size_t len;
@@ -45,10 +51,7 @@ int streamInqHistorySize(int streamID)
 #ifdef HAVE_LIBNETCDF
   stream_t *streamptr = stream_to_pointer(streamID);
 
-  if ( streamptr->filetype == CDI_FILETYPE_NC  ||
-       streamptr->filetype == CDI_FILETYPE_NC2 ||
-       streamptr->filetype == CDI_FILETYPE_NC4 ||
-       streamptr->filetype == CDI_FILETYPE_NC4C )
+  if ( filetypeIsNetCDF(streamptr->filetype) )
     {
       size = cdfInqHistorySize(streamptr);
     }
@@ -64,10 +67,7 @@ void streamInqHistoryString(int streamID, char *history)
 #ifdef HAVE_LIBNETCDF
   stream_t *streamptr = stream_to_pointer(streamID);
 
-  if ( streamptr->filetype == CDI_FILETYPE_NC  ||
-       streamptr->filetype == CDI_FILETYPE_NC2 ||
-       streamptr->filetype == CDI_FILETYPE_NC4 ||
-       streamptr->filetype == CDI_FILETYPE_NC4C )
+  if ( filetypeIsNetCDF(streamptr->filetype) )
     {
       cdfInqHistoryString(streamptr, history);
     }
diff --git a/libcdi/src/stream_ieg.c b/libcdi/src/stream_ieg.c
index ea209be..13a53af 100644
--- a/libcdi/src/stream_ieg.c
+++ b/libcdi/src/stream_ieg.c
@@ -395,16 +395,16 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
     {
     case ZAXIS_SURFACE:
       {
-        pdbDefLevel(pdb, IEG_LTYPE_SURFACE, 0, (int)zaxisInqLevel(zaxisID, levelID));
+        pdbDefLevel(pdb, IEG_LTYPE_SURFACE, 0, (int)(zaxisInqLevel(zaxisID, levelID)));
 	break;
       }
     case ZAXIS_HYBRID:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-          pdbDefLevel(pdb, IEG_LTYPE_HYBRID_LAYER, (int)zaxisInqLbound(zaxisID, levelID),
-                      (int)zaxisInqUbound(zaxisID, levelID));
+          pdbDefLevel(pdb, IEG_LTYPE_HYBRID_LAYER, (int)(zaxisInqLbound(zaxisID, levelID)),
+                      (int)(zaxisInqUbound(zaxisID, levelID)));
 	else
-          pdbDefLevel(pdb, IEG_LTYPE_HYBRID, 0, (int)zaxisInqLevel(zaxisID, levelID));
+          pdbDefLevel(pdb, IEG_LTYPE_HYBRID, 0, (int)(zaxisInqLevel(zaxisID, levelID)));
 
 	int vctsize = zaxisInqVctSize(zaxisID);
 	if ( vctsize > 100 )
@@ -460,9 +460,9 @@ void iegDefLevel(int *pdb, int *gdb, double *vct, int zaxisID, int levelID)
     case ZAXIS_DEPTH_BELOW_LAND:
       {
 	if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
-          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH_LAYER, (int)zaxisInqLbound(zaxisID, levelID), (int)zaxisInqUbound(zaxisID, levelID));
+          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH_LAYER, (int)(zaxisInqLbound(zaxisID, levelID)), (int)(zaxisInqUbound(zaxisID, levelID)));
 	else
-          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH, 0, (int)zaxisInqLevel(zaxisID, levelID));
+          pdbDefLevel(pdb, IEG_LTYPE_LANDDEPTH, 0, (int)(zaxisInqLevel(zaxisID, levelID)));
 
 	break;
       }
diff --git a/libcdi/src/stream_srv.c b/libcdi/src/stream_srv.c
index 3aa74f0..3bce61f 100644
--- a/libcdi/src/stream_srv.c
+++ b/libcdi/src/stream_srv.c
@@ -699,7 +699,7 @@ void srvWriteVarSliceDP(stream_t *streamptr, int varID, int levID, const double
 
   int header[8];
   header[0] = pnum;
-  header[1] = (int) zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID);
+  header[1] = (int)(zaxisInqLevel(vlistInqVarZaxis(vlistID, varID), levID));
   header[2] = streamptr->tsteps[tsID].taxis.vdate;
   header[3] = streamptr->tsteps[tsID].taxis.vtime;
 
diff --git a/libcdi/src/stream_write.c b/libcdi/src/stream_write.c
index 21014e0..36f62cc 100644
--- a/libcdi/src/stream_write.c
+++ b/libcdi/src/stream_write.c
@@ -133,13 +133,15 @@ void streamWriteVarF(int streamID, int varID, const float *data, int nmiss)
   int (*myCdiStreamWriteVar_)(int streamID, int varID, int memtype, const void *data, int nmiss)
     = (int (*)(int, int, int, const void *, int))
     namespaceSwitchGet(NSSWITCH_STREAM_WRITE_VAR_).func;
-  
+
   if ( myCdiStreamWriteVar_(streamID, varID, MEMTYPE_FLOAT, (const void *) data, nmiss) )
     {
       // In case the file format does not support single precision writing,
-      // we fall back to double precision writing, converting the data on the fly.
-      size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(streamInqVlist(streamID), varID));
-      elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(streamInqVlist(streamID), varID));
+      // we fall back to double precision writing, converting the data
+      // on the fly.
+      int vlistID = streamInqVlist(streamID);
+      size_t elementCount = (size_t) gridInqSize(vlistInqVarGrid(vlistID, varID));
+      elementCount *= (size_t) zaxisInqSize(vlistInqVarZaxis(vlistID, varID));
       double *conversionBuffer = (double *) Malloc(elementCount*sizeof(*conversionBuffer));
       for ( size_t i = elementCount; i--; ) conversionBuffer[i] = (double) data[i];
       myCdiStreamWriteVar_(streamID, varID, MEMTYPE_DOUBLE, (const void *) conversionBuffer, nmiss);
diff --git a/libcdi/src/table.c b/libcdi/src/table.c
index 387afc7..05c62e3 100644
--- a/libcdi/src/table.c
+++ b/libcdi/src/table.c
@@ -377,71 +377,50 @@ int tableRead(const char *tablefile)
 
 static int tableFromEnv(int modelID, int tablenum)
 {
-  int tableID = CDI_UNDEFID;
   char tablename[256] = {'\0'};
-  int tablenamefound = 0;
+  size_t tablenameLen = 0;
+  int instID;
 
-  const char *modelName;
-  if ( (modelName = modelInqNamePtr(modelID)) )
-    {
-      strcpy(tablename, modelName);
-      if ( tablenum )
-	{
-	  size_t len = strlen(tablename);
-	  sprintf(tablename+len, "_%03d", tablenum);
-	}
-      tablenamefound = 1;
+  const char *name2Use;
+  {
+    const char *modelName, *instName;
+    if ( (modelName = modelInqNamePtr(modelID)) )
+      name2Use = modelName;
+    else if ( (instID = modelInqInstitut(modelID)) != CDI_UNDEFID
+              && (instName = institutInqNamePtr(instID)) )
+      name2Use = instName;
+    else
+      return CDI_UNDEFID;
+  }
+  tablenameLen = strlen(name2Use);
+  memcpy(tablename, name2Use, tablenameLen);
+  if ( tablenum )
+    tablenameLen
+      += (size_t)(sprintf(tablename+tablenameLen, "_%03d", tablenum));
+  size_t lenp = 0, lenf = tablenameLen;
+  if ( tablePath )
+    lenp = strlen(tablePath);
+  /* if (tablePath) printf("tablePath = %s\n", tablePath); */
+  /* if (tablename) printf("tableName = %s\n", tablename); */
+  char *tablefile = (char *) Malloc(lenp+lenf+3);
+  if ( tablePath )
+    {
+      strcpy(tablefile, tablePath);
+      strcat(tablefile, "/");
     }
   else
-    {
-      int instID = modelInqInstitut(modelID);
-      if ( instID != CDI_UNDEFID )
-	{
-          const char *instName;
-	  if ( (instName = institutInqNamePtr(instID)) )
-	    {
-	      strcpy(tablename, instName);
-	      if ( tablenum )
-		{
-		  size_t len = strlen(tablename);
-		  sprintf(tablename+len, "_%03d", tablenum);
-		}
-	      tablenamefound = 1;
-	    }
-	}
-    }
+    tablefile[0] = '\0';
+  strcat(tablefile, tablename);
+  /* if (tablefile) printf("tableFile = %s\n", tablefile); */
 
-  if ( tablenamefound )
+  int tableID = tableRead(tablefile);
+  if ( tableID != CDI_UNDEFID )
     {
-      size_t lenp = 0, lenf;
-      char *tablefile = NULL;
-      if ( tablePath )
-	lenp = strlen(tablePath);
-      lenf = strlen(tablename);
-      /* if (tablePath) printf("tablePath = %s\n", tablePath); */
-      /* if (tablename) printf("tableName = %s\n", tablename); */
-      tablefile = (char *) Malloc(lenp+lenf+3);
-      if ( tablePath )
-	{
-	  strcpy(tablefile, tablePath);
-	  strcat(tablefile, "/");
-	}
-      else
-	tablefile[0] = '\0';
-      strcat(tablefile, tablename);
-      /* if (tablefile) printf("tableFile = %s\n", tablefile); */
-
-      tableID = tableRead(tablefile);
-      if ( tableID != CDI_UNDEFID )
-	{
-	  tableDefModelID(tableID, modelID);
-	  tableDefNum(tableID, tablenum);
-	}
-      /* printf("tableID = %d %s\n", tableID, tablefile); */
-
-      Free(tablefile);
+      tableDefModelID(tableID, modelID);
+      tableDefNum(tableID, tablenum);
     }
-
+  /* printf("tableID = %d %s\n", tableID, tablefile); */
+  Free(tablefile);
   return (tableID);
 }
 
diff --git a/libcdi/src/taxis.c b/libcdi/src/taxis.c
index 2223932..b54e4f4 100644
--- a/libcdi/src/taxis.c
+++ b/libcdi/src/taxis.c
@@ -3,7 +3,6 @@
 #endif
 
 #include <stddef.h>
-#include <string.h>
 
 #include "cdi.h"
 #include "calendar.h"
@@ -17,6 +16,7 @@
 #include "resource_handle.h"
 #include "resource_unpack.h"
 
+
 static int DefaultTimeType = TAXIS_ABSOLUTE;
 static int DefaultTimeUnit = TUNIT_HOUR;
 
@@ -104,24 +104,15 @@ static int  TAXIS_Debug = 0;   /* If set to 1, debugging */
 
 const char *tunitNamePtr(int unitID)
 {
-  const char *name;
   int size = sizeof(Timeunits)/sizeof(*Timeunits);
-
-  if ( unitID > 0 && unitID < size )
-    name = Timeunits[unitID];
-  else
-    name = Timeunits[0];
-
-  return name;
+  return (unitID > 0 && unitID < size) ? Timeunits[unitID] : Timeunits[0];
 }
 
 #if 0
 static
 void taxis_defaults(void)
 {
-  char *timeunit;
-
-  timeunit = getenv("TIMEUNIT");
+  char *timeunit = getenv("TIMEUNIT");
   if ( timeunit )
     {
       if ( strcmp(timeunit, "minutes") == 0 )
@@ -172,6 +163,7 @@ void taxisDefaultValue(taxis_t* taxisptr)
   taxisptr->fc_period   = 0;
   taxisptr->name        = NULL;
   taxisptr->longname    = NULL;
+  taxisptr->units       = NULL;
 }
 
 static taxis_t *
@@ -192,7 +184,7 @@ taxisNewEntry(cdiResH resH)
 }
 
 static
-void taxisInit (void)
+void taxisInit(void)
 {
   static bool taxisInitialized = false;
 
@@ -204,16 +196,6 @@ void taxisInit (void)
   if ( env ) TAXIS_Debug = atoi(env);
 }
 
-#if 0
-static
-void taxis_copy(taxis_t *taxisptr2, taxis_t *taxisptr1)
-{
-  int taxisID2 = taxisptr2->self;
-  memcpy(taxisptr2, taxisptr1, sizeof(taxis_t));
-  taxisptr2->self = taxisID2;
-}
-#endif
-
 /*
 @Function  taxisCreate
 @Title     Create a Time axis
@@ -266,6 +248,7 @@ void taxisDestroyKernel(taxis_t *taxisptr)
 {
   delete_refcount_string(taxisptr->name);
   delete_refcount_string(taxisptr->longname);
+  delete_refcount_string(taxisptr->units);
 }
 
 /*
@@ -311,11 +294,12 @@ int taxisDuplicate(int taxisID1)
 
 void taxisDefType(int taxisID, int type)
 {
-  taxis_t *taxisptr = ( taxis_t * ) reshGetVal ( taxisID, &taxisOps );
+  taxis_t *taxisptr = (taxis_t *) reshGetVal(taxisID, &taxisOps);
 
-  if (taxisptr->type != type)
+  if ( taxisptr->type != type )
     {
       taxisptr->type = type;
+      if ( taxisptr->units ) delete_refcount_string(taxisptr->units);
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -391,6 +375,7 @@ void taxisDefRdate(int taxisID, int rdate)
   if (taxisptr->rdate != rdate)
     {
       taxisptr->rdate = rdate;
+      if ( taxisptr->units ) delete_refcount_string(taxisptr->units);
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -416,6 +401,7 @@ void taxisDefRtime(int taxisID, int rtime)
   if (taxisptr->rtime != rtime)
     {
       taxisptr->rtime = rtime;
+      if ( taxisptr->units ) delete_refcount_string(taxisptr->units);
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -505,6 +491,7 @@ void taxisDefTunit(int taxisID, int unit)
   if (taxisptr->unit != unit)
     {
       taxisptr->unit = unit;
+      if ( taxisptr->units ) delete_refcount_string(taxisptr->units);
       reshSetStatus(taxisID, &taxisOps, RESH_DESYNC_IN_USE);
     }
 }
@@ -909,6 +896,18 @@ void ptaxisDefLongname(taxis_t *taxisptr, const char *longname)
 }
 
 
+void ptaxisDefUnits(taxis_t *taxisptr, const char *units)
+{
+  if ( units )
+    {
+      size_t len = strlen(units);
+      delete_refcount_string(taxisptr->units);
+      char *taxisunits = taxisptr->units = new_refcount_string(len);
+      strcpy(taxisunits, units);
+    }
+}
+
+
 static void
 cdiDecodeTimevalue(int timeunit, double timevalue, int *days, int *secs)
 {
@@ -1318,21 +1317,15 @@ double cdiEncodeTimeval(int date, int time, taxis_t *taxis)
 	{
 	  int year, month, day;
 	  cdiDecodeDate(date, &year, &month, &day);
-          timevalue = date/100;
-	  if ( day != 0 )
-            {
-              if ( date < 0 ) timevalue -= 0.5;
-              else            timevalue += 0.5;
-            }
+          timevalue = date/100
+            + copysign((double)(day != 0) * 0.5, (double)date);
         }
       else
 	{
 	  int hour, minute, second;
 	  cdiDecodeTime(time, &hour, &minute, &second);
-	  if ( date < 0 )
-	    timevalue = -(-date + (hour*3600 + minute*60 + second)/86400.);
-	  else
-	    timevalue =    date + (hour*3600 + minute*60 + second)/86400.;
+          timevalue = copysign(1.0, (double)date)
+            * (fabs((double)date) + (hour*3600 + minute*60 + second)/86400.);
 	}
     }
   else
@@ -1377,8 +1370,10 @@ void ptaxisCopy(taxis_t *dest, taxis_t *source)
   dest->climatology = source->climatology;
   delete_refcount_string(dest->name);
   delete_refcount_string(dest->longname);
+  delete_refcount_string(dest->units);
   dest->name = dup_refcount_string(source->name);
   dest->longname = dup_refcount_string(source->longname);
+  dest->units = dup_refcount_string(source->units);
   if (dest->self != CDI_UNDEFID)
     reshSetStatus(dest->self, &taxisOps, RESH_DESYNC_IN_USE);
   reshUnlock ();
@@ -1465,7 +1460,7 @@ taxisTxCode ( void )
   return TAXIS;
 }
 
-enum { taxisNint = 21 };
+enum { taxisNint = 22 };
 
 static int
 taxisGetPackSize(void *p, void *context)
@@ -1477,8 +1472,9 @@ taxisGetPackSize(void *p, void *context)
     + (taxisptr->name ?
        serializeGetSize((int)strlen(taxisptr->name), CDI_DATATYPE_TXT, context) : 0)
     + (taxisptr->longname ?
-       serializeGetSize((int)strlen(taxisptr->longname), CDI_DATATYPE_TXT,
-                        context) : 0);
+       serializeGetSize((int)strlen(taxisptr->longname), CDI_DATATYPE_TXT, context) : 0)
+    + (taxisptr->units ?
+       serializeGetSize((int)strlen(taxisptr->units), CDI_DATATYPE_TXT, context) : 0);
   return packBufferSize;
 }
 
@@ -1543,6 +1539,15 @@ taxisUnpack(char * unpackBuffer, int unpackBufferSize, int * unpackBufferPos,
       longname[len] = '\0';
       taxisP->longname = longname;
     }
+  if (intBuffer[idx])
+    {
+      int len = intBuffer[idx];
+      char *units = new_refcount_string((size_t)len);
+      serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
+                      units, len, CDI_DATATYPE_TXT, context);
+      units[len] = '\0';
+      taxisP->units = units;
+    }
 
   reshSetStatus(taxisP->self, &taxisOps,
                 reshGetStatus(taxisP->self, &taxisOps) & ~RESH_SYNC_BIT);
@@ -1581,6 +1586,7 @@ taxisPack(void * voidP, void * packBuffer, int packBufferSize, int * packBufferP
   intBuffer[idx++] = taxisP->vtime_ub;
   intBuffer[idx++] = taxisP->name ? (int)strlen(taxisP->name) : 0;
   intBuffer[idx++] = taxisP->longname ? (int)strlen(taxisP->longname) : 0;
+  intBuffer[idx++] = taxisP->units ? (int)strlen(taxisP->units) : 0;
 
   serializePack(intBuffer, taxisNint, CDI_DATATYPE_INT,
                 packBuffer, packBufferSize, packBufferPos, context);
@@ -1593,6 +1599,9 @@ taxisPack(void * voidP, void * packBuffer, int packBufferSize, int * packBufferP
   if (taxisP->longname)
     serializePack(taxisP->longname, intBuffer[16], CDI_DATATYPE_TXT,
                   packBuffer, packBufferSize, packBufferPos, context);
+  if (taxisP->units)
+    serializePack(taxisP->units, intBuffer[16], CDI_DATATYPE_TXT,
+                  packBuffer, packBufferSize, packBufferPos, context);
 
 }
 
diff --git a/libcdi/src/taxis.h b/libcdi/src/taxis.h
index 7f1f3ed..c2ac50c 100644
--- a/libcdi/src/taxis.h
+++ b/libcdi/src/taxis.h
@@ -33,6 +33,7 @@ typedef struct {
   double  fc_period;      // forecast time period
   char   *name;
   char   *longname;
+  char   *units;
 }
 taxis_t;
 
@@ -47,7 +48,8 @@ double   vtime2timeval(int vdate, int vtime, taxis_t *taxis);
 
 void    ptaxisDefDatatype(taxis_t *taxisptr, int datatype);
 void    ptaxisDefName(taxis_t *taxisptr, const char *name);
-void    ptaxisDefLongname(taxis_t *taxisptr, const char *name);
+void    ptaxisDefLongname(taxis_t *taxisptr, const char *longname);
+void    ptaxisDefUnits(taxis_t *taxisptr, const char *units);
 void    taxisDestroyKernel(taxis_t *taxisptr);
 #if !defined (SX)
 extern const resOps taxisOps;
diff --git a/libcdi/src/util.c b/libcdi/src/util.c
index 8125f8e..52fb248 100644
--- a/libcdi/src/util.c
+++ b/libcdi/src/util.c
@@ -19,48 +19,6 @@
 #include "binary.h"
 
 
-void cdiPrintDatatypes(void)
-{
-#define XSTRING(x)	#x
-#define STRING(x)	XSTRING(x)
-  fprintf (stderr, "+-------------+-------+\n"
-           "| types       | bytes |\n"
-           "+-------------+-------+\n"
-           "| void *      |   %3d |\n"
-           "+-------------+-------+\n"
-           "| char        |   %3d |\n"
-           "+-------------+-------+\n"
-           "| bool        |   %3d |\n"
-           "| short       |   %3d |\n"
-           "| int         |   %3d |\n"
-           "| long        |   %3d |\n"
-           "| long long   |   %3d |\n"
-           "| size_t      |   %3d |\n"
-           "| off_t       |   %3d |\n"
-           "+-------------+-------+\n"
-           "| float       |   %3d |\n"
-           "| double      |   %3d |\n"
-           "| long double |   %3d |\n"
-           "+-------------+-------+\n\n"
-           "+-------------+-----------+\n"
-           "| INT32       | %-9s |\n"
-           "| INT64       | %-9s |\n"
-           "| FLT32       | %-9s |\n"
-           "| FLT64       | %-9s |\n"
-           "+-------------+-----------+\n"
-           "\n  byte ordering is %s\n\n",
-           (int) sizeof(void *), (int) sizeof(char), (int) sizeof(bool),
-           (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long),
-           (int) sizeof(size_t), (int) sizeof(off_t),
-           (int) sizeof(float), (int) sizeof(double), (int) sizeof(long double),
-           STRING(INT32), STRING(INT64), STRING(FLT32), STRING(FLT64),
-           ((HOST_ENDIANNESS == CDI_BIGENDIAN) ? "BIGENDIAN"
-            : ((HOST_ENDIANNESS == CDI_LITTLEENDIAN) ? "LITTLEENDIAN"
-               : "Unhandled endianness!")));
-#undef STRING
-#undef XSTRING
-}
-
 static const char uuidFmt[] = "%02hhx%02hhx%02hhx%02hhx-"
   "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-"
   "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx";
@@ -198,8 +156,8 @@ void cdiCreateUUID(unsigned char *uuid)
 void cdiCreateUUID(unsigned char *uuid)
 {
   static int uuid_seeded = 0;
-  static char uuid_rand_state[31 * sizeof (long)];
 #ifndef _SX
+  static char uuid_rand_state[31 * sizeof (long)];
   char *caller_rand_state;
   if (uuid_seeded)
     caller_rand_state = setstate(uuid_rand_state);
@@ -220,6 +178,27 @@ void cdiCreateUUID(unsigned char *uuid)
   for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
     uuid[i] = (unsigned char)random();
 #else
+  unsigned short caller_rand_state[3];
+  {
+    static unsigned short our_rand_state[3];
+    if (!uuid_seeded)
+      {
+        struct timeval tv;
+        int status = gettimeofday(&tv, NULL);
+        if (status != 0)
+          {
+            perror("failed seed generation!");
+            exit(1);
+          }
+        unsigned seed = tv.tv_sec ^ tv.tv_usec;
+        our_rand_state[0] = 0x330E;
+        our_rand_state[1] = (unsigned short)(seed & 0xFFFFU);
+        our_rand_state[2] = (unsigned short)((seed >> 16) & 0xFFFFU);
+      }
+    unsigned short *p = seed48(our_rand_state);
+    uuid_seeded = 1;
+    memcpy(caller_rand_state, p, sizeof (caller_rand_state));
+  }
   for (size_t i = 0; i < CDI_UUID_SIZE; ++i)
     uuid[i] = (unsigned char)lrand48();
 #endif
@@ -229,6 +208,8 @@ void cdiCreateUUID(unsigned char *uuid)
   uuid[7] = (unsigned char)((uuid[7] & 0x0f) | (4 << 4));
 #ifndef _SX
   setstate(caller_rand_state);
+#else
+  seed48(caller_rand_state);
 #endif
 }
 #endif
diff --git a/libcdi/src/varscan.c b/libcdi/src/varscan.c
index 810bc3d..e174967 100644
--- a/libcdi/src/varscan.c
+++ b/libcdi/src/varscan.c
@@ -91,12 +91,12 @@ vartable_t;
 
 static vartable_t *vartable;
 static unsigned varTablesize = 0;
-static unsigned nvars = 0;
+static unsigned varTableUsed = 0;
 
 static
 void paramInitEntry(unsigned varID, int param)
 {
-  vartable[varID].varID          = varID;
+  vartable[varID].varID          = (int)varID;
   vartable[varID].param          = param;
   vartable[varID].prec           = 0;
   vartable[varID].tsteptype      = TSTEP_INSTANT;
@@ -171,7 +171,7 @@ void varFree(void)
 {
   if ( CDI_Debug ) Message("call to varFree");
 
-  for ( unsigned varID = 0; varID < nvars; varID++ )
+  for ( size_t varID = 0; varID < varTableUsed; varID++ )
     {
       if ( vartable[varID].recordTable )
         {
@@ -205,7 +205,7 @@ void varFree(void)
 
   vartable = NULL;
   varTablesize = 0;
-  nvars = 0;
+  varTableUsed = 0;
 
   if ( Vct )
     Free(Vct);
@@ -369,7 +369,7 @@ paramNewEntry(int param)
     {
       vartable = (vartable_t *) Realloc(vartable, (size_t)(varTablesize *= 2)
                                         * sizeof (vartable_t));
-      for ( unsigned i = varID; i < varTablesize; i++ )
+      for ( size_t i = varID; i < varTablesize; i++ )
         {
           vartable[i].param = UNDEF_PARAM;
           vartable[i].opt_grib_kvpair      = NULL;
@@ -433,7 +433,7 @@ void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
 
   if ( varID == (unsigned) CDI_UNDEFID )
     {
-      nvars++;
+      varTableUsed++;
       varID = paramNewEntry(param);
       vartable[varID].gridID     = gridID;
       vartable[varID].zaxistype  = zaxistype;
@@ -581,21 +581,21 @@ void cdi_generate_vars(stream_t *streamptr)
   char name[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
   int vlistID = streamptr->vlistID;
 
-  int *varids = (int *) Malloc(nvars*sizeof(int));
-  for ( unsigned varID = 0; varID < nvars; varID++ ) varids[varID] = (int)varID;
+  int *varids = (int *) Malloc(varTableUsed*sizeof(int));
+  for ( size_t varID = 0; varID < varTableUsed; varID++ ) varids[varID] = (int)varID;
   /*
   if ( streamptr->sortparam )
     {
-      struct paraminfo *varInfo = (struct paraminfo *) Malloc((size_t)nvars * sizeof(struct paraminfo));
+      struct paraminfo *varInfo = (struct paraminfo *) Malloc((size_t)varTableUsed * sizeof(struct paraminfo));
 
-      for ( unsigned varID = 0; varID < nvars; varID++ )
+      for ( unsigned varID = 0; varID < varTableUsed; varID++ )
 	{
 	  varInfo[varID].varid = varids[varID];
 	  varInfo[varID].param = vartable[varID].param;
 	  varInfo[varID].ltype = vartable[varID].ltype1;
 	}
-      qsort(varInfo, (size_t)nvars, sizeof(struct paraminfo), cmp_param);
-      for ( unsigned varID = 0; varID < nvars; varID++ )
+      qsort(varInfo, (size_t)varTableUsed, sizeof(struct paraminfo), cmp_param);
+      for ( unsigned varID = 0; varID < varTableUsed; varID++ )
 	{
 	  varids[varID] = varInfo[varID].varid;
 	}
@@ -604,10 +604,10 @@ void cdi_generate_vars(stream_t *streamptr)
 
   if ( streamptr->sortname )
     {
-      qsort(vartable, (size_t)nvars, sizeof(vartable_t), cmp_varname);
+      qsort(vartable, (size_t)varTableUsed, sizeof(vartable_t), cmp_varname);
     }
   */
-  for ( unsigned index = 0; index < nvars; index++ )
+  for ( size_t index = 0; index < varTableUsed; index++ )
     {
       int varid      = varids[index];
 
@@ -830,7 +830,7 @@ void cdi_generate_vars(stream_t *streamptr)
       if ( tableID != CDI_UNDEFID ) vlistDefVarTable(vlistID, varID, tableID);
     }
 
-  for ( unsigned index = 0; index < nvars; index++ )
+  for ( size_t index = 0; index < varTableUsed; index++ )
     {
       int varid = varids[index];
       unsigned nlevels = vartable[varid].recordTable[0].nlevels;
diff --git a/libcdi/src/vlist.h b/libcdi/src/vlist.h
index 0b633a7..bcba360 100644
--- a/libcdi/src/vlist.h
+++ b/libcdi/src/vlist.h
@@ -5,7 +5,7 @@
 #include "config.h"
 #endif
 
-#ifndef  _ERROR_H
+#ifndef  ERROR_H
 #include "error.h"
 #endif
 
diff --git a/libcdi/tests/Makefile.in b/libcdi/tests/Makefile.in
index 1e41e34..fdc9c1d 100644
--- a/libcdi/tests/Makefile.in
+++ b/libcdi/tests/Makefile.in
@@ -127,6 +127,7 @@ am__aclocal_m4_deps =  \
 	$(top_srcdir)/m4/acx_lt_problems.m4 \
 	$(top_srcdir)/m4/acx_option_search_libs.m4 \
 	$(top_srcdir)/m4/acx_options.m4 \
+	$(top_srcdir)/m4/acx_prog_cc_posix.m4 \
 	$(top_srcdir)/m4/acx_sl_fc_mod_path_flag.m4 \
 	$(top_srcdir)/m4/acx_sl_mod_suffix.m4 \
 	$(top_srcdir)/m4/asx_tr_arg.m4 $(top_srcdir)/m4/asx_unset.m4 \
diff --git a/libcdi/tests/pio_write.c b/libcdi/tests/pio_write.c
index 9d5af8f..3f194f0 100644
--- a/libcdi/tests/pio_write.c
+++ b/libcdi/tests/pio_write.c
@@ -100,6 +100,10 @@ parse_long_option(struct model_config *restrict setup,
                   int pioConfHandle, pioRoleFunc *pioRoleAssign,
                   const char *str)
 {
+#ifndef USE_MPI
+  (void)pioConfHandle;
+  (void)pioRoleAssign;
+#endif
   static const char cacheRedistStr[] = "cache-redists",
     pioRoleSchemeOptionStr[] = "pio-role-scheme",
     uuidCreateOptionStr[] = "no-create-uuid";
diff --git a/libcdi/tests/simple_model.c b/libcdi/tests/simple_model.c
index 3f6bed3..4753858 100644
--- a/libcdi/tests/simple_model.c
+++ b/libcdi/tests/simple_model.c
@@ -281,7 +281,7 @@ modelRun(struct model_config setup, MPI_Comm comm)
                       for (size_t i = 1; i < (size_t)comm_size; ++i)
                         displs[i] = displs[i - 1] + chunks[i - 1];
                     }
-                  xmpi(MPI_Gatherv(varslice, (size_t)chunkSize, MPI_DOUBLE,
+                  xmpi(MPI_Gatherv(varslice, chunk, MPI_DOUBLE,
                                    var, chunks, displs, MPI_DOUBLE, 0, comm));
 #else
                   var = varslice;
@@ -321,14 +321,13 @@ modelRun(struct model_config setup, MPI_Comm comm)
               }
             for (size_t i = 0; i < (size_t)nVars; ++i)
               {
-                uint32_t cksum;
-                int code;
-                cksum = memcrc_finish(&varDesc[i].checksum_state,
-                                      (off_t)((varDesc[i].size
-                                               * sizeof (var[0])
-                                               + sizeof (int) * 2)
-                                              * (size_t)setup.nts));
-                code = vlistInqVarCode(vlistID, varDesc[i].id);
+                uint32_t cksum
+                  = memcrc_finish(&varDesc[i].checksum_state,
+                                  (off_t)((varDesc[i].size
+                                           * sizeof (var[0])
+                                           + sizeof (int) * 2)
+                                          * (size_t)setup.nts));
+                int code = vlistInqVarCode(vlistID, varDesc[i].id);
                 if (fprintf(tablefp, "%08lx %d\n", (unsigned long)cksum,
                             code) < 0)
                   {
diff --git a/libcdi/tests/stream_cksum.c b/libcdi/tests/stream_cksum.c
index 93baaa4..4f8e458 100644
--- a/libcdi/tests/stream_cksum.c
+++ b/libcdi/tests/stream_cksum.c
@@ -2,6 +2,7 @@
 #  include "config.h"
 #endif
 
+#include <stdbool.h>
 #include <stdio.h>
 
 #include "cdi.h"
@@ -9,25 +10,30 @@
 #include "stream_cksum.h"
 #include "dmemory.h"
 
+const char *zaxisNamePtr(int zaxistype);
+
 struct cksum_table *
 cksum_stream(const char *fname, size_t *table_len)
 {
-  int taxisID, vlistID, streamID;
-  int nvars, ngrids, nzaxis;
-  int i;
+  int nvars;
   uint32_t *checksum_state = NULL;
-  struct var_size_t
+  enum directionZ {
+    DIRECTION_DOWN=1, DIRECTION_NONE, DIRECTION_UP
+  };
+  struct var_desc_t
   {
     int x, y, z;
+    enum directionZ zDirection;
+    int code;
     size_t chars;
-  } *varSize = NULL;
+  } *varDesc = NULL;
   size_t var_size_max_chars = 0;
   double *buf = NULL;
   struct cksum_table *file_vars = NULL;
 
   do {
     // Open the dataset
-    streamID = streamOpenRead(fname);
+    int streamID = streamOpenRead(fname);
     if ( streamID < 0 )
       {
         fprintf(stderr, "Cannot open data input file %s: %s\n",
@@ -37,11 +43,13 @@ cksum_stream(const char *fname, size_t *table_len)
       }
 
     // Get the variable list of the dataset
-    vlistID = streamInqVlist(streamID);
-
+    int vlistID = streamInqVlist(streamID);
+    int fileType = streamInqFiletype(streamID);
+    bool isLegacyFile = fileType == CDI_FILETYPE_SRV
+      || fileType == CDI_FILETYPE_EXT;
     nvars = vlistNvars(vlistID);
-    ngrids = vlistNgrids(vlistID);
-    nzaxis = vlistNzaxis(vlistID);
+    int ngrids = vlistNgrids(vlistID);
+    int nzaxis = vlistNzaxis(vlistID);
     if (nzaxis < 0 || ngrids < 0)
       {
         fprintf(stderr, "Error in grid/zaxis count query %d:%d\n",
@@ -50,58 +58,97 @@ cksum_stream(const char *fname, size_t *table_len)
         break;
       }
     checksum_state = (uint32_t *) Calloc((size_t)nvars, sizeof (checksum_state[0]));
-    varSize = (struct var_size_t *)malloc((size_t)nvars * sizeof (varSize[0]));
+    varDesc = (struct var_desc_t *)malloc((size_t)nvars * sizeof (varDesc[0]));
 
-    for (i = 0; i < nvars; ++i)
+    for (int varIdx = 0; varIdx < nvars; ++varIdx)
       {
-        int grid = vlistInqVarGrid(vlistID, i), gridType;
-        int zaxis = vlistInqVarZaxis(vlistID, i);
-        if (grid == CDI_UNDEFID || zaxis == CDI_UNDEFID)
+        int grid = vlistInqVarGrid(vlistID, varIdx), gridType,
+          varCode = vlistInqVarCode(vlistID, varIdx);
+        varDesc[varIdx].code = varCode;
+        int zaxisID = vlistInqVarZaxis(vlistID, varIdx);
+        if (grid == CDI_UNDEFID || zaxisID == CDI_UNDEFID)
           {
             fputs("error in axis/grid inquiry\n", stderr);
             nvars = -1;
             break;
           }
-      if ((varSize[i].z = zaxisInqSize(zaxis)) <= 0)
-        {
-          fputs("invalid Z-axis found\n", stderr);
-          nvars = -1;
-          break;
-        }
-      if ((gridType = gridInqType(grid)) != GRID_LONLAT
-          && gridType != GRID_GENERIC)
-        {
-          fprintf(stderr, "unexpected non-lonlat grid found: %d\n",
-                  gridType);
-          nvars = -1;
-          break;
-        }
-      if ((varSize[i].x = gridInqXsize(grid)) < 0)
-        {
-          fprintf(stderr, "invalid X-size found: %d\n", varSize[i].x);
-          nvars = -1;
-          break;
-        }
-      if (varSize[i].x == 0) varSize[i].x = 1;
-      if ((varSize[i].y = gridInqYsize(grid)) < 0)
-        {
-          fprintf(stderr, "invalid Y-size found: %d\n", varSize[i].y);
-          nvars = -1;
+        int zSize;
+        if ((zSize = varDesc[varIdx].z = zaxisInqSize(zaxisID)) <= 0)
+          {
+            fputs("invalid Z-axis found\n", stderr);
+            nvars = -1;
+            break;
+          }
+        if (isLegacyFile)
+          varDesc[varIdx].zDirection = DIRECTION_NONE;
+        else if (zSize > 1)
+          {
+            double lev[2];
+            for (int levIdx = 0; levIdx < 2; ++levIdx)
+              lev[levIdx] = zaxisInqLevel(zaxisID, levIdx);
+            int zaxistype = zaxisInqType(zaxisID);
+            switch (zaxistype)
+              {
+              case ZAXIS_PRESSURE:
+                if (lev[0] < lev[1])
+                  varDesc[varIdx].zDirection = DIRECTION_DOWN;
+                else if (lev[1] < lev[0])
+                  varDesc[varIdx].zDirection = DIRECTION_UP;
+                else
+                  {
+                    fprintf(stderr,
+                            "unexpected level ordering on z-Axis for variable"
+                            " code %d found: lev[0]=%g, lev[1]=%g\n",
+                            varCode, lev[0], lev[1]);
+                    nvars = -1;
+                  }
+                break;
+              default:
+                fprintf(stderr, "unexpected type of z-Axis for variable"
+                        " code %d found: %s\n",
+                        varCode, zaxisNamePtr(zaxistype));
+                nvars = -1;
+              }
+          }
+        else
+          varDesc[varIdx].zDirection = DIRECTION_NONE;
+        if (nvars == -1)
           break;
-        }
-      if (varSize[i].y == 0) varSize[i].y = 1;
-      varSize[i].chars = (size_t)varSize[i].x * (size_t)varSize[i].y
-        * (size_t)varSize[i].z * sizeof (buf[0]);
-      if (var_size_max_chars < varSize[i].chars)
-        var_size_max_chars = varSize[i].chars;
-    }
+        if ((gridType = gridInqType(grid)) != GRID_LONLAT
+            && gridType != GRID_GENERIC)
+          {
+            fprintf(stderr, "unexpected non-lonlat grid found: %d\n",
+                    gridType);
+            nvars = -1;
+            break;
+          }
+        if ((varDesc[varIdx].x = gridInqXsize(grid)) < 0)
+          {
+            fprintf(stderr, "invalid X-size found: %d\n", varDesc[varIdx].x);
+            nvars = -1;
+            break;
+          }
+        if (varDesc[varIdx].x == 0) varDesc[varIdx].x = 1;
+        if ((varDesc[varIdx].y = gridInqYsize(grid)) < 0)
+          {
+            fprintf(stderr, "invalid Y-size found: %d\n", varDesc[varIdx].y);
+            nvars = -1;
+            break;
+          }
+        if (varDesc[varIdx].y == 0) varDesc[varIdx].y = 1;
+        varDesc[varIdx].chars
+        = (size_t)varDesc[varIdx].x * (size_t)varDesc[varIdx].y
+        * (size_t)varDesc[varIdx].z * sizeof (buf[0]);
+        if (var_size_max_chars < varDesc[varIdx].chars)
+          var_size_max_chars = varDesc[varIdx].chars;
+      }
     buf = (double*)malloc(var_size_max_chars);
 
     if (nvars == -1)
       break;
 
     // Get the Time axis from the variable list
-    taxisID = vlistInqTaxis(vlistID);
+    int taxisID = vlistInqTaxis(vlistID);
 
     int tsID = 0;
     // Inquire the time step
@@ -110,24 +157,39 @@ cksum_stream(const char *fname, size_t *table_len)
         // Get the verification date and time
         int vdatetime[2] = { taxisInqVtime(taxisID), taxisInqVdate(taxisID) };
         // Read var1 and var2
-        for (i = 0; i < nvars; ++i)
+        for (int varIdx = 0; varIdx < nvars; ++varIdx)
           {
             int nmiss;
-            streamReadVar(streamID, i, buf, &nmiss);
-            memcrc_r(checksum_state + i, (const unsigned char *)vdatetime, sizeof (vdatetime));
-            memcrc_r(checksum_state + i, (const unsigned char *)buf,
-                     varSize[i].chars);
+            streamReadVar(streamID, varIdx, buf, &nmiss);
+            memcrc_r(checksum_state + varIdx, (const unsigned char *)vdatetime,
+                     sizeof (vdatetime));
+            if (varDesc[varIdx].zDirection == DIRECTION_UP
+                || varDesc[varIdx].zDirection == DIRECTION_NONE)
+              memcrc_r(checksum_state + varIdx, (const unsigned char *)buf,
+                       varDesc[varIdx].chars);
+            else
+              {
+                size_t nlev = (size_t)varDesc[varIdx].z,
+                  charsPerLev = (size_t)varDesc[varIdx].x
+                  * (size_t)varDesc[varIdx].y * sizeof (buf[0]);
+                for (size_t lev = 0; lev < nlev; ++lev)
+                  memcrc_r(checksum_state + varIdx,
+                           (const unsigned char *)buf + (nlev - lev - 1)
+                           * charsPerLev, charsPerLev);
+              }
           }
         ++tsID;
       }
 
-    file_vars = (struct cksum_table *)malloc((size_t)nvars * sizeof (file_vars[0]));
-    for (i = 0; i < nvars; ++i)
+    file_vars = (struct cksum_table *)malloc((size_t)nvars
+                                             * sizeof (file_vars[0]));
+    for (int varIdx = 0; varIdx < nvars; ++varIdx)
       {
-        file_vars[i].code = vlistInqVarCode(vlistID, i);
-        file_vars[i].cksum
-          = memcrc_finish(checksum_state + i,
-                          (off_t)((varSize[i].chars + sizeof (int) * 2) * (size_t)tsID));
+        file_vars[varIdx].code = varDesc[varIdx].code;
+        file_vars[varIdx].cksum
+          = memcrc_finish(checksum_state + varIdx,
+                          (off_t)((varDesc[varIdx].chars + sizeof (int) * 2)
+                                  * (size_t)tsID));
       }
     // Close the input stream
     streamClose(streamID);
@@ -136,10 +198,19 @@ cksum_stream(const char *fname, size_t *table_len)
 
   // free resources
   free(checksum_state);
-  free(varSize);
+  free(varDesc);
   free(buf);
   *table_len = (size_t)nvars;
 
   return file_vars;
 }
 
+/*
+ * Local Variables:
+ * c-file-style: "Java"
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * show-trailing-whitespace: t
+ * require-trailing-newline: t
+ * End:
+ */
diff --git a/m4/acx_options.m4 b/m4/acx_options.m4
index 0b9a84a..4aa09ce 100644
--- a/m4/acx_options.m4
+++ b/m4/acx_options.m4
@@ -518,6 +518,19 @@ AC_ARG_ENABLE([all-static],
               [enable_all_static=no])
 AC_MSG_RESULT([$enable_all_static])
 AM_CONDITIONAL([ENABLE_ALL_STATIC],[test x$enable_all_static = 'xyes'])
+#  ----------------------------------------------------------------------
+#  Build CDO with HIRLAM extensions
+AC_MSG_CHECKING([for HIRLAM extensions])
+AC_ARG_ENABLE([hirlam-extensions],
+              [AS_HELP_STRING([--enable-hirlam-extensions],[HIRLAM extensions [default=no]])],
+              [AS_IF([test "x$enable_hirlam_extensions" != "xno"],
+                    [AC_DEFINE(HIRLAM_EXTENSIONS,[1],[Define to 1 for HIRLAM extensions])
+                     enable_hirlam_extensions=yes],
+                    [enable_hirlam_extensions=no])],
+              [enable_hirlam_extensions=no])
+AC_MSG_RESULT([$enable_hirlam_extensions])
+AM_CONDITIONAL([ENABLE_HIRLAM_EXTENSIONS],[test x$enable_hirlam_extensions = 'xyes'])
+#
 ])
 dnl
 dnl Local Variables:
diff --git a/src/Adisit.c b/src/Adisit.c
index abc593a..1c31e99 100644
--- a/src/Adisit.c
+++ b/src/Adisit.c
@@ -261,7 +261,7 @@ void *Adisit(void *argument)
 
   int vlistID2 = vlistCreate();
 
-  int tisID2 = vlistDefVar(vlistID2, gridID, zaxisID, TIME_VARIABLE);
+  int tisID2 = vlistDefVar(vlistID2, gridID, zaxisID, TSTEP_INSTANT);
   if ( operatorID == ADISIT )
     {
       vlistDefVarParam(vlistID2, tisID2, cdiEncodeParam(20, 255, 255));
@@ -280,7 +280,7 @@ void *Adisit(void *argument)
   vlistDefVarMissval(vlistID2, tisID2, tis.missval);
   vlistDefVarDatatype(vlistID2, tisID2, datatype);
 
-  int saoID2 = vlistDefVar(vlistID2, gridID, zaxisID, TIME_VARIABLE);
+  int saoID2 = vlistDefVar(vlistID2, gridID, zaxisID, TSTEP_INSTANT);
   vlistDefVarParam(vlistID2, saoID2, cdiEncodeParam(5, 255, 255));
   vlistDefVarName(vlistID2, saoID2, "s");
   vlistDefVarLongname(vlistID2, saoID2, "Sea water salinity");
diff --git a/src/Afterburner.c b/src/Afterburner.c
index f730fd0..565e86c 100644
--- a/src/Afterburner.c
+++ b/src/Afterburner.c
@@ -1,3 +1,15 @@
+/* ============================================================= */
+/*                                                               */
+/* postprocessing program for ECHAM data and ECMWF analysis data */
+/*                                                               */
+/* Luis     Kornblueh   - MPI    Hamburg                         */
+/* Uwe      Schulzweida - MPI    Hamburg                         */
+/* Arno     Hellbach    - DKRZ   Hamburg                         */
+/* Edilbert Kirk        - MI Uni Hamburg                         */
+/* Michael  Ponater     - DLR    Oberpfaffenhofen                */
+/*                                                               */
+/* ============================================================= */
+
 #if defined(HAVE_CONFIG_H)
 #include "config.h"
 #endif
@@ -1792,19 +1804,20 @@ void after_postcntl(struct Control *globs, struct Variable *vars)
 	    units    = vlistInqVarUnitsPtr(globs->ivlistID, ivarID);
 	  }
 
-	if ( globs->Mean != 2 )
+        int tsteptype = (globs->Mean) ? TSTEP_AVG : TSTEP_INSTANT;
+
+        if ( globs->Mean != 2 )
 	  {
 	    vlistDefTaxis(globs->ovlistID, globs->taxisID2);
-	    ovarID = vlistDefVar(globs->ovlistID, ogridID, ozaxisID, TIME_VARIABLE);
+	    ovarID = vlistDefVar(globs->ovlistID, ogridID, ozaxisID, tsteptype);
 	    vlistDefVarCode(globs->ovlistID, ovarID, code);
 	    vars[code].ovarID = ovarID;
 	    vlistDefVarInstitut(globs->ovlistID, ovarID, instID);
 	    vlistDefVarModel(globs->ovlistID, ovarID, modelID);
 	    vlistDefVarTable(globs->ovlistID, ovarID, tableID);
-	    if ( globs->Mean ) vlistDefVarTimave(globs->ovlistID, ovarID, 1);
-	    if ( name )        vlistDefVarName(globs->ovlistID, ovarID, name);
-	    if ( longname )    vlistDefVarLongname(globs->ovlistID, ovarID, longname);
-	    if ( units )       vlistDefVarUnits(globs->ovlistID, ovarID, units);
+	    if ( name )     vlistDefVarName(globs->ovlistID, ovarID, name);
+	    if ( longname ) vlistDefVarLongname(globs->ovlistID, ovarID, longname);
+	    if ( units )    vlistDefVarUnits(globs->ovlistID, ovarID, units);
 	    vlistDefVarDatatype(globs->ovlistID, ovarID, datatype);
 	    vlistDefVarMissval(globs->ovlistID, ovarID, vars[code].missval);
 	  }
@@ -1812,16 +1825,15 @@ void after_postcntl(struct Control *globs, struct Variable *vars)
 	if ( globs->Mean >= 2 )
 	  {
 	    vlistDefTaxis(globs->ovlistID2, globs->taxisID2);
-	    ovarID2 = vlistDefVar(globs->ovlistID2, ogridID, ozaxisID, TIME_VARIABLE);
+	    ovarID2 = vlistDefVar(globs->ovlistID2, ogridID, ozaxisID, tsteptype);
 	    vlistDefVarCode(globs->ovlistID2, ovarID2, code);
 	    vars[code].ovarID2 = ovarID2;
 	    vlistDefVarInstitut(globs->ovlistID2, ovarID2, instID);
 	    vlistDefVarModel(globs->ovlistID2, ovarID2, modelID);
 	    vlistDefVarTable(globs->ovlistID2, ovarID2, tableID);
-	    if ( globs->Mean ) vlistDefVarTimave(globs->ovlistID2, ovarID2, 1);
-	    if ( name )        vlistDefVarName(globs->ovlistID2, ovarID2, name);
-	    if ( longname )    vlistDefVarLongname(globs->ovlistID2, ovarID2, longname);
-	    if ( units )       vlistDefVarUnits(globs->ovlistID2, ovarID2, units);
+	    if ( name )     vlistDefVarName(globs->ovlistID2, ovarID2, name);
+	    if ( longname ) vlistDefVarLongname(globs->ovlistID2, ovarID2, longname);
+	    if ( units )    vlistDefVarUnits(globs->ovlistID2, ovarID2, units);
 	    vlistDefVarDatatype(globs->ovlistID2, ovarID2, datatype);
 	    vlistDefVarMissval(globs->ovlistID2, ovarID2, vars[code].missval);
 	  }
diff --git a/src/Arith.c b/src/Arith.c
index 62ba000..e6e6901 100644
--- a/src/Arith.c
+++ b/src/Arith.c
@@ -38,12 +38,10 @@ void *Arith(void *argument)
   enum {FILL_NONE, FILL_TS, FILL_VAR, FILL_VARTS, FILL_FILE};
   int filltype = FILL_NONE;
   int nmiss;
-  int nrecs, nrecs2, nvars = 0, nlev;
+  int nrecs, nrecs2, nvars = 0;
   int nlevels2 = 1;
   int varID, levelID;
-  int varID2, levelID2;
-  int offset;
-  int lfill1, lfill2;
+  int levelID2;
   int *varnmiss2 = NULL;
   int **varnmiss = NULL;
   double *vardata2 = NULL;
@@ -90,6 +88,7 @@ void *Arith(void *argument)
   if ( ntsteps1 == 0 ) ntsteps1 = 1;
   if ( ntsteps2 == 0 ) ntsteps2 = 1;
 
+  bool lfill1, lfill2;
   if ( vlistNvars(vlistID1) == 1 && vlistNvars(vlistID2) == 1 )
     {
       lfill2 = vlistNrecs(vlistID1) != 1 && vlistNrecs(vlistID2) == 1;
@@ -182,8 +181,8 @@ void *Arith(void *argument)
 	  varnmiss = (int **) Malloc(nvars*sizeof(int *));
 	  for ( varID = 0; varID < nvars; varID++ )
 	    {
-	      gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID));
-	      nlev     = zaxisInqSize(vlistInqVarZaxis(vlistIDx2, varID));
+	      int gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID));
+	      int nlev     = zaxisInqSize(vlistInqVarZaxis(vlistIDx2, varID));
 	      vardata[varID]  = (double*) Malloc(nlev*gridsize*sizeof(double));
 	      varnmiss[varID] = (int*) Malloc(nlev*sizeof(int));
 	    }
@@ -250,6 +249,7 @@ void *Arith(void *argument)
 	  streamInqRecord(streamIDx1, &varID, &levelID);
 	  streamReadRecord(streamIDx1, fieldx1->ptr, &nmiss);
           fieldx1->nmiss = (size_t) nmiss;
+          int varID2 = varID;
           
 	  if ( tsID == 0 || filltype == FILL_NONE || filltype == FILL_FILE || filltype == FILL_VARTS )
 	    {
@@ -266,23 +266,23 @@ void *Arith(void *argument)
 
 	      if ( filltype == FILL_TS )
 		{
-		  gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID));
-		  offset   = gridsize*levelID;
+		  int gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID));
+		  int offset   = gridsize*levelID;
 		  memcpy(vardata[varID]+offset, fieldx2->ptr, gridsize*sizeof(double));
 		  varnmiss[varID][levelID] = fieldx2->nmiss;
 		}
 	      else if ( lstatus && (filltype == FILL_VAR || filltype == FILL_VARTS) )
 		{
-		  gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, 0));
-		  offset   = gridsize*levelID2;
+		  int gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, 0));
+		  int offset   = gridsize*levelID2;
 		  memcpy(vardata2+offset, fieldx2->ptr, gridsize*sizeof(double));
 		  varnmiss2[levelID2] = fieldx2->nmiss;
 		}
 	    }
 	  else if ( filltype == FILL_TS )
 	    {
-	      gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID2));
-	      offset   = gridsize*levelID;
+	      int gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, varID2));
+	      int offset   = gridsize*levelID;
 	      memcpy(fieldx2->ptr, vardata[varID]+offset, gridsize*sizeof(double));
 	      fieldx2->nmiss = varnmiss[varID][levelID];
 	    }
@@ -292,10 +292,10 @@ void *Arith(void *argument)
 
 	  if ( filltype == FILL_VAR || filltype == FILL_VARTS )
 	    {
-	      gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, 0));
+	      int gridsize = gridInqSize(vlistInqVarGrid(vlistIDx2, 0));
 	      levelID2 = 0;
 	      if ( nlevels2 > 1 ) levelID2 = levelID;
-	      offset   = gridsize*levelID2;
+	      int offset   = gridsize*levelID2;
 	      memcpy(fieldx2->ptr, vardata2+offset, gridsize*sizeof(double));
 	      fieldx2->nmiss   = varnmiss2[levelID2];
 	      fieldx2->grid    = vlistInqVarGrid(vlistIDx2, 0);
diff --git a/src/Arithlat.c b/src/Arithlat.c
index 51d5aa5..a5a422d 100644
--- a/src/Arithlat.c
+++ b/src/Arithlat.c
@@ -85,9 +85,10 @@ void *Arithlat(void *argument)
 	      gridID0 = gridID;
 
 	      gridtype = gridInqType(gridID);
+              int projtype = (gridtype == GRID_PROJECTION) ? gridInqProjType(gridID) : -1;
 	      if ( gridtype == GRID_LONLAT      ||
 		   gridtype == GRID_GAUSSIAN    ||
-		   gridtype == GRID_LCC )
+		   projtype == CDI_PROJ_LCC )
 		{
 		  gridID = gridToCurvilinear(gridID, 0);
 		}
diff --git a/src/Change_e5slm.c b/src/Change_e5slm.c
index 9cbcdc2..04043b6 100644
--- a/src/Change_e5slm.c
+++ b/src/Change_e5slm.c
@@ -30,11 +30,9 @@
 void *Change_e5slm(void *argument)
 {
   char name[CDI_MAX_NAME];
-  int nrecs, code;
+  int nrecs;
   int varID, levelID;
   int nmiss;
-  long i;
-  double minval, maxval;
 
   cdoInitialize(argument);
 
@@ -64,7 +62,7 @@ void *Change_e5slm(void *argument)
 
   int vlistIDslm = streamInqVlist(streamIDslm);
 
-  int gridsize = gridInqSize(vlistInqVarGrid(vlistIDslm, 0));
+  long gridsize = gridInqSize(vlistInqVarGrid(vlistIDslm, 0));
 
   double *array = (double*) Malloc(gridsize*sizeof(double));
   double *cland = (double*) Malloc(gridsize*sizeof(double));
@@ -77,13 +75,14 @@ void *Change_e5slm(void *argument)
 
   if ( nmiss > 0 ) cdoAbort("SLM with missing values are unsupported!");
 
+  double minval, maxval;
   minmaxval(gridsize, cland, NULL, &minval, &maxval);
   if ( minval < 0 || maxval > 1 )
     cdoWarning("Values of SLM out of bounds! (minval=%g, maxval=%g)", minval , maxval);
 
   streamClose(streamIDslm);
 
-  for ( i = 0; i < gridsize; ++i )
+  for ( long i = 0; i < gridsize; ++i )
     {
       if ( cland[i] > 0 )
 	lsea[i] = false;
@@ -100,7 +99,7 @@ void *Change_e5slm(void *argument)
       if ( gridsize != gridInqSize(vlistInqVarGrid(vlistID1, varID)) )
 	cdoAbort("gridsize differ!");
 
-      code = vlistInqVarCode(vlistID1, varID);
+      int code = vlistInqVarCode(vlistID1, varID);
       vlistInqVarName(vlistID1, varID, name);
 
       if ( code < 0 )
@@ -135,23 +134,23 @@ void *Change_e5slm(void *argument)
 	  streamInqRecord(streamID1, &varID, &levelID);
 	  streamReadRecord(streamID1, array, &nmiss);
 
-	  code = codes[varID];
+	  int code = codes[varID];
 	  if ( code == 172 )
 	    {
 	      cdoPrint("SLM changed!");
-	      for ( i = 0; i < gridsize; ++i )
+	      for ( long i = 0; i < gridsize; ++i )
 		array[i] = cland[i];
 	    }
 	  else if ( code == 99 )
 	    {
 	      cdoPrint("ALAKE set all values to zero!");
-	      for ( i = 0; i < gridsize; ++i )
+	      for ( long i = 0; i < gridsize; ++i )
 		array[i] = 0;
 	    }
 	  else if ( code == 232 )
 	    {
 	      cdoPrint("GLAC set sea points to %g!", array[0]);
-	      for ( i = 0; i < gridsize; ++i )
+	      for ( long i = 0; i < gridsize; ++i )
 		if ( cland[i] < 0.5 ) array[i] = array[0];
 	    }
 	  else if ( code ==  70 || code ==  71 || code == 140 ||
@@ -160,7 +159,7 @@ void *Change_e5slm(void *argument)
 		    code == 229 )
 	    {
 	      cdoPrint("Code %d set sea points to %g!", code, array[0]);
-	      for ( i = 0; i < gridsize; ++i )
+	      for ( long i = 0; i < gridsize; ++i )
 		if ( lsea[i] ) array[i] = array[0];
 	    }
 
diff --git a/src/Collgrid.c b/src/Collgrid.c
index 3ad02f6..2feb150 100644
--- a/src/Collgrid.c
+++ b/src/Collgrid.c
@@ -29,6 +29,9 @@ typedef struct
   int streamID;
   int vlistID;
   int gridID;
+  int nmiss;
+  int gridsize;
+  int *gridindex;
   double *array;
 } ens_file_t;
 
@@ -80,7 +83,7 @@ int cmpxy_gt(const void *s1, const void *s2)
 }
 
 static
-int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks)
+int genGrid(int ngrids, int nfiles, ens_file_t *ef, bool ginit, int igrid, int nxblocks)
 {
   bool lsouthnorth = true;
   bool lregular = false;
@@ -93,7 +96,7 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
 
   int gridID   = vlistGrid(ef[0].vlistID, igrid);
   int gridtype = gridInqType(gridID);
-  if ( gridtype == GRID_GENERIC && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 )
+  if ( ngrids > 1 && gridtype == GRID_GENERIC && gridInqXsize(gridID) == 0 && gridInqYsize(gridID) == 0 )
     return gridID2;
 
   int *xsize = (int*) Malloc(nfiles*sizeof(int));
@@ -110,13 +113,15 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
         lregular = true;
       else if ( gridtype == GRID_CURVILINEAR )
         lcurvilinear = true;
-      else if ( gridtype == GRID_GENERIC && gridInqXsize(gridID) > 0 && gridInqYsize(gridID) > 0 )
+      else if ( gridtype == GRID_GENERIC /*&& gridInqXsize(gridID) > 0 && gridInqYsize(gridID) > 0*/ )
         ;
       else
 	cdoAbort("Unsupported grid type: %s!", gridNamePtr(gridtype));
 
       xsize[fileID] = gridInqXsize(gridID);
       ysize[fileID] = gridInqYsize(gridID);
+      if ( xsize[fileID] == 0 ) xsize[fileID] = 1;
+      if ( ysize[fileID] == 0 ) ysize[fileID] = 1;
 
       if ( lregular )
         {
@@ -235,7 +240,7 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
       yoff[j+1] = yoff[j] + ysize[idx];
     }
 
-  if ( gridindex != NULL )
+  if ( ginit == false )
     {
       for ( int fileID = 0; fileID < nfiles; fileID++ )
 	{
@@ -257,7 +262,7 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
                     xvals2[offset+j*xsize2+i] = xvals[idx][ij];
                     yvals2[offset+j*xsize2+i] = yvals[idx][ij];
                   }
-		gridindex[idx][ij++] = offset+j*xsize2+i;
+                ef[idx].gridindex[ij++] = offset+j*xsize2+i;
 	      }
 	}
     }
@@ -300,11 +305,8 @@ int genGrid(int nfiles, ens_file_t *ef, int **gridindex, int igrid, int nxblocks
 void *Collgrid(void *argument)
 {
   int nxblocks = -1;
-  int varID;
-  int nrecs, nrecs0;
-  int levelID;
-  int nmiss;
-  double missval;
+  int varID, levelID;
+  int nrecs0;
 
   cdoInitialize(argument);
     
@@ -330,12 +332,13 @@ void *Collgrid(void *argument)
     vlistCompare(vlistID1, ef[fileID].vlistID, CMP_NAME | CMP_NLEVEL);
 
   int nvars = vlistNvars(vlistID1);
-  bool *vars  = (bool*) Malloc(nvars*sizeof(bool));
+  bool *vars = (bool*) Malloc(nvars*sizeof(bool));
   for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
-  bool *vars1  = (bool*) Malloc(nvars*sizeof(bool));
+  bool *vars1 = (bool*) Malloc(nvars*sizeof(bool));
   for ( varID = 0; varID < nvars; varID++ ) vars1[varID] = false;
 
   int nsel = operatorArgc();
+  int noff = 0;
 
   if ( nsel > 0 )
     {
@@ -345,6 +348,7 @@ void *Collgrid(void *argument)
       if ( len == -1 )
         {
           nsel--;
+          noff++;
           nxblocks = parameter2int(operatorArgv()[0]);
         }
     }
@@ -355,7 +359,7 @@ void *Collgrid(void *argument)
     }
   else
     {
-      char **argnames = operatorArgv();
+      char **argnames = operatorArgv() + noff;
 
       if ( cdoVerbose )
 	for ( int i = 0; i < nsel; i++ )
@@ -397,18 +401,14 @@ void *Collgrid(void *argument)
 	}
     }
 
-  int gridsize;
-  int gridsizemax = 0;
   for ( int fileID = 0; fileID < nfiles; fileID++ )
     {
-      gridsize = vlistGridsizeMax(ef[fileID].vlistID);
-      if ( gridsize > gridsizemax ) gridsizemax = gridsize;
+      int gridsize = vlistGridsizeMax(ef[fileID].vlistID);
+      ef[fileID].gridsize = gridsize;
+      ef[fileID].gridindex = (int*) Malloc(gridsize*sizeof(int));
+      ef[fileID].array = (double*) Malloc(gridsize*sizeof(double));
     }
 
-  for ( int fileID = 0; fileID < nfiles; fileID++ )
-    ef[fileID].array = (double*) Malloc(gridsizemax*sizeof(double));
-
-
   int vlistID2 = vlistCreate();
   vlistCopyFlag(vlistID2, vlistID1);
   /*
@@ -427,9 +427,6 @@ void *Collgrid(void *argument)
   int ngrids2 = vlistNgrids(vlistID2);
 
   int *gridIDs = (int*) Malloc(ngrids2*sizeof(int));
-  int **gridindex = (int **) Malloc(nfiles*sizeof(int *));
-  for ( int fileID = 0; fileID < nfiles; fileID++ )
-    gridindex[fileID] = (int*) Malloc(gridsizemax*sizeof(int));
 
   bool ginit = false;
   for ( int i2 = 0; i2 < ngrids2; ++i2 )
@@ -442,11 +439,11 @@ void *Collgrid(void *argument)
 
       if ( !ginit )
 	{
-	  gridIDs[i2] = genGrid(nfiles, ef, gridindex, i1, nxblocks);
+	  gridIDs[i2] = genGrid(ngrids2, nfiles, ef, ginit, i1, nxblocks);
 	  if ( gridIDs[i2] != -1 ) ginit = true;
 	}
       else
-	gridIDs[i2] = genGrid(nfiles, ef, NULL, i1, nxblocks);
+	gridIDs[i2] = genGrid(ngrids2, nfiles, ef, ginit, i1, nxblocks);
     }
 
 
@@ -483,7 +480,7 @@ void *Collgrid(void *argument)
       
   streamDefVlist(streamID2, vlistID2);
 	  
-  double *array2 = (double*) Malloc(gridsize2*sizeof(double));
+  double *array2 = (gridsize2 > 0) ? (double*) Malloc(gridsize2*sizeof(double)) : NULL;
 
   int tsID = 0;
   do
@@ -491,7 +488,7 @@ void *Collgrid(void *argument)
       nrecs0 = streamInqTimestep(ef[0].streamID, tsID);
       for ( int fileID = 1; fileID < nfiles; fileID++ )
 	{
-	  nrecs = streamInqTimestep(ef[fileID].streamID, tsID);
+	  int nrecs = streamInqTimestep(ef[fileID].streamID, tsID);
 	  if ( nrecs != nrecs0 )
 	    cdoAbort("Number of records at time step %d of %s and %s differ!", tsID+1, cdoStreamName(0)->args, cdoStreamName(fileID)->args);
 	}
@@ -505,10 +502,10 @@ void *Collgrid(void *argument)
 	  streamInqRecord(ef[0].streamID, &varID, &levelID);
 	  if ( cdoVerbose && tsID == 0 ) printf(" tsID, recID, varID, levelID %d %d %d %d\n", tsID, recID, varID, levelID);
 
-	  for ( int fileID = 0; fileID < nfiles; fileID++ )
+	  for ( int fileID = 1; fileID < nfiles; fileID++ )
 	    {
 	      int varIDx, levelIDx;
-	      if ( fileID > 0 ) streamInqRecord(ef[fileID].streamID, &varIDx, &levelIDx);
+	      streamInqRecord(ef[fileID].streamID, &varIDx, &levelIDx);
 	    }
 
 	  if ( vlistInqFlag(vlistID1, varID, levelID) == TRUE )
@@ -517,21 +514,21 @@ void *Collgrid(void *argument)
 	      int levelID2 = vlistFindLevel(vlistID2, varID, levelID);
 	      if ( cdoVerbose && tsID == 0 ) printf("varID %d %d levelID %d %d\n", varID, varID2, levelID, levelID2);
 
-	      missval = vlistInqVarMissval(vlistID2, varID2);
+	      double missval = vlistInqVarMissval(vlistID2, varID2);
 	      for ( int i = 0; i < gridsize2; i++ ) array2[i] = missval;
 
 #if defined(_OPENMP)
-#pragma omp parallel for default(shared) private(nmiss)
+#pragma omp parallel for default(shared)
 #endif
 	      for ( int fileID = 0; fileID < nfiles; fileID++ )
 		{
-		  streamReadRecord(ef[fileID].streamID, ef[fileID].array, &nmiss);
+		  streamReadRecord(ef[fileID].streamID, ef[fileID].array, &ef[fileID].nmiss);
 
 		  if ( vars[varID2] )
 		    {
-		      gridsize = gridInqSize(vlistInqVarGrid(ef[fileID].vlistID, varID));
+                      int gridsize = ef[fileID].gridsize;
 		      for ( int i = 0; i < gridsize; ++i )
-			array2[gridindex[fileID][i]] = ef[fileID].array[i];
+			array2[ef[fileID].gridindex[i]] = ef[fileID].array[i];
 		    }
 		}
 
@@ -539,14 +536,14 @@ void *Collgrid(void *argument)
 
 	      if ( vars[varID2] )
 		{
-		  nmiss = 0;
+		  int nmiss = 0;
 		  for ( int i = 0; i < gridsize2; i++ )
 		    if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
 
 		  streamWriteRecord(streamID2, array2, nmiss);
 		}
 	      else
-		streamWriteRecord(streamID2, ef[0].array, 0);
+		streamWriteRecord(streamID2, ef[0].array, ef[0].nmiss);
 	    }
 	}
 
@@ -560,7 +557,10 @@ void *Collgrid(void *argument)
   streamClose(streamID2);
 
   for ( int fileID = 0; fileID < nfiles; fileID++ )
-    if ( ef[fileID].array ) Free(ef[fileID].array);
+    {
+      if ( ef[fileID].gridindex ) Free(ef[fileID].gridindex);
+      if ( ef[fileID].array ) Free(ef[fileID].array);
+    }
 
   if ( ef ) Free(ef);
   if ( array2 ) Free(array2);
diff --git a/src/Copy.c b/src/Copy.c
index 3e5e88a..1620907 100644
--- a/src/Copy.c
+++ b/src/Copy.c
@@ -28,6 +28,14 @@
 #include "pstream.h"
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+int streamGrbInqDataScanningMode(void);
+#if defined (__cplusplus)
+}
+#endif
+
 void *Copy(void *argument)
 {
   bool lconstvars = true;
@@ -49,6 +57,14 @@ void *Copy(void *argument)
   int SELALL  = cdoOperatorAdd("selall", 0, 0, NULL);
   int SZIP    = cdoOperatorAdd("szip",   0, 0, NULL);
 
+#ifdef HIRLAM_EXTENSIONS
+  // KEEP in mind the difference between copy and selall with respect to unpacking and repacking the GRIB information!
+  // Especially when setting the DataScanningMode.
+  printf("cdo copy/selall : UNCHANGED_RECORD=%d\n",UNCHANGED_RECORD);
+  //if (cdiGribDataScanningMode != -1) lcopy = false;
+  printf("cdo copy/selall : cdiGribDataScanningMode=%d; lcopy=%d\n", streamGrbInqDataScanningMode(), lcopy);
+#endif //#ifdef HIRLAM_EXTENSIONS
+
   int operatorID = cdoOperatorID();
 
   if ( operatorID == SZIP )
diff --git a/src/Derivepar.c b/src/Derivepar.c
index b32a1e0..78d08bc 100644
--- a/src/Derivepar.c
+++ b/src/Derivepar.c
@@ -36,7 +36,6 @@ double *vlist_hybrid_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlevf);
 void *Derivepar(void *argument)
 {
   int mode;
-  enum {ECHAM_MODE, WMO_MODE};
   int nrecs;
   int i, offset;
   int varID, levelID;
@@ -129,6 +128,14 @@ void *Derivepar(void *argument)
 	      mode = ECHAM_MODE;
 	      echam_gribcodes(&gribcodes);
 	    }
+          //  KNMI: HIRLAM model version 7.2 uses tableNum=1    (LAMH_D11*)
+          //  KNMI: HARMONIE model version 36 uses tableNum=1   (grib*)   (opreational NWP version)
+          //  KNMI: HARMONIE model version 38 uses tableNum=253 (grib,grib_md) and tableNum=1 (grib_sfx) (research version)
+	  else if ( tableNum == 1 || tableNum == 253 )
+	    {
+	      mode = HIRLAM_MODE;
+	      hirlam_harmonie_gribcodes(&gribcodes);
+	    }
 	  else
 	    mode = -1;
 	}
diff --git a/src/Distgrid.c b/src/Distgrid.c
index 8e60cca..87147dd 100644
--- a/src/Distgrid.c
+++ b/src/Distgrid.c
@@ -268,8 +268,8 @@ void *Distgrid(void *argument)
   int xinc = nx/nxblocks;
   int yinc = ny/nyblocks;
 
-  if ( nx%xinc != 0 ) xinc++;
-  if ( ny%yinc != 0 ) yinc++;
+  if ( nx%xinc && nx%(xinc+1) ) xinc++;
+  if ( ny%yinc && ny%(yinc+1) ) yinc++;
 
   int nsplit = nxblocks*nyblocks;
   if ( nsplit > MAX_BLOCKS ) cdoAbort("Too many blocks (max = %d)!", MAX_BLOCKS);
diff --git a/src/Ensstat.c b/src/Ensstat.c
index 5bdd142..81be6df 100644
--- a/src/Ensstat.c
+++ b/src/Ensstat.c
@@ -120,18 +120,18 @@ void *Ensstat(void *argument)
   int taxisID2 = taxisDuplicate(taxisID1);
   vlistDefTaxis(vlistID2, taxisID2);
 
-  int gridsize = vlistGridsizeMax(vlistID1);
+  int gridsizemax = vlistGridsizeMax(vlistID1);
 
   for ( int fileID = 0; fileID < nfiles; fileID++ )
-    ef[fileID].array = (double*) Malloc(gridsize*sizeof(double));
+    ef[fileID].array = (double*) Malloc(gridsizemax*sizeof(double));
 
-  double *array2 = (double *) Malloc(gridsize*sizeof(double));
+  double *array2 = (double *) Malloc(gridsizemax*sizeof(double));
 
   int nvars = vlistNvars(vlistID2);
   double *count2 = NULL;
   if ( count_data )
     {
-      count2 = (double *) Malloc(gridsize*sizeof(double));
+      count2 = (double *) Malloc(gridsizemax*sizeof(double));
       for ( int varID = 0; varID < nvars; ++varID )
 	{
 	  char name[CDI_MAX_NAME];
@@ -198,14 +198,13 @@ void *Ensstat(void *argument)
 	  for ( int fileID = 0; fileID < nfiles; fileID++ )
 	    {
               int nmiss;
-	      int streamID = ef[fileID].streamID;
-	      streamInqRecord(streamID, &varID, &levelID);
-	      streamReadRecord(streamID, ef[fileID].array, &nmiss);
+	      streamInqRecord(ef[fileID].streamID, &varID, &levelID);
+	      streamReadRecord(ef[fileID].streamID, ef[fileID].array, &nmiss);
               ef[fileID].missval = vlistInqVarMissval(ef[fileID].vlistID, varID);
 	    }
 
 	  int gridID = vlistInqVarGrid(vlistID1, varID);
-	  gridsize = gridInqSize(gridID);
+	  int gridsize = gridInqSize(gridID);
 	  double missval = vlistInqVarMissval(vlistID1, varID);
 
 	  int nmiss = 0;
diff --git a/src/Exprf.c b/src/Exprf.c
index 45ec76e..07f46e7 100644
--- a/src/Exprf.c
+++ b/src/Exprf.c
@@ -214,7 +214,7 @@ int params_add_ts(parse_param_t *parse_arg)
       params[varID].name     = strdup("_ts");
       params[varID].gridID   = parse_arg->pointID;
       params[varID].zaxisID  = parse_arg->surfaceID;
-      params[varID].steptype = TIME_VARIABLE;
+      params[varID].steptype = TSTEP_INSTANT;
       params[varID].ngp      = 1;
       params[varID].nlev     = 1;
       
@@ -367,6 +367,14 @@ void *Expr(void *argument)
       varIDmap[varID] = pidx;
     }
 
+  if ( cdoVerbose ) 
+    {
+      for ( int varID = 0; varID < nvars1; varID++ )
+        if ( parse_arg.needed[varID] )
+          printf("needed: %d %s\n", varID, parse_arg.params[varID].name);
+      cdoPrint("vlistNvars(vlistID1)=%d, vlistNvars(vlistID2)=%d",vlistNvars(vlistID1),vlistNvars(vlistID2));
+    }
+
   int nvars2 = vlistNvars(vlistID2);
   if ( nvars2 == 0 ) cdoAbort("No output variable found!");
 
diff --git a/src/Filedes.c b/src/Filedes.c
index 0cbecc0..706aa20 100644
--- a/src/Filedes.c
+++ b/src/Filedes.c
@@ -27,10 +27,10 @@
 #include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
+#include "grid.h"
 #include "util.h"
 
 
-void cdo_print_grid(int gridID, int opt);
 void cdo_print_zaxis(int zaxisID);
 
 void cdo_print_attributes(FILE *fp, int cdiID, int varID, int nblanks)
diff --git a/src/Fillmiss.c b/src/Fillmiss.c
index 2f940bf..b3cbecb 100644
--- a/src/Fillmiss.c
+++ b/src/Fillmiss.c
@@ -272,8 +272,8 @@ void fillmiss_one_step(field_type *field1, field_type *field2, int maxfill)
 
 
 int grid_search_nbr(struct gridsearch *gs, int num_neighbors, int *restrict nbr_add, double *restrict nbr_dist, double plon, double plat);
-double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, int *restrict nbr_mask, const int *restrict nbr_add, double *restrict nbr_dist);
-unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const int *restrict nbr_mask, int *restrict nbr_add, double *restrict nbr_dist);
+double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, bool *restrict nbr_mask, const int *restrict nbr_add, double *restrict nbr_dist);
+unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const bool *restrict nbr_mask, int *restrict nbr_add, double *restrict nbr_dist);
 
 static
 void setmisstodis(field_type *field1, field_type *field2, int num_neighbors)
@@ -340,7 +340,7 @@ void setmisstodis(field_type *field1, field_type *field2, int num_neighbors)
 
   if ( nv != nvals ) cdoAbort("Internal problem, number of valid values differ!");
   
-  int nbr_mask[num_neighbors];    /* mask at nearest neighbors                   */
+  bool nbr_mask[num_neighbors];   /* mask at nearest neighbors                   */
   int nbr_add[num_neighbors];     /* source address at nearest neighbors         */
   double nbr_dist[num_neighbors]; /* angular distance four nearest neighbors     */
 
diff --git a/src/Gradsdes.c b/src/Gradsdes.c
index 57ff45c..8fde12d 100644
--- a/src/Gradsdes.c
+++ b/src/Gradsdes.c
@@ -407,38 +407,38 @@ void dumpmap()
 static
 void ctl_xydef(FILE *gdp, int gridID, bool *yrev)
 {
-  int gridtype;
   int i, j;
-  int xsize, ysize;
   double xfirst, yfirst, xinc, yinc;
-  double *xvals, *yvals;
 
   *yrev = false;
 
-  xsize  = gridInqXsize(gridID);
-  ysize  = gridInqYsize(gridID);
+  int xsize  = gridInqXsize(gridID);
+  int ysize  = gridInqYsize(gridID);
 
-  gridtype = gridInqType(gridID);
+  int gridtype = gridInqType(gridID);
+  int projtype = gridInqProjType(gridID);
 
   /* XDEF */
 
-  if ( gridtype == GRID_LCC )
+  if ( gridtype == GRID_PROJECTION && projtype == CDI_PROJ_LCC )
     {
-      double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
       double xmin = 1.e10, xmax = -1.e10, ymin = 1.e10, ymax = -1.e10;
       double xrange, yrange;
-      int projflag, scanflag;
       int nx, ny, ni;
       double inc[] = { 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01, 0.005, 0.002, 0.001 };
 
-      gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                 &projflag, &scanflag);
+      double xinc = gridInqXinc(gridID);
+      double yinc = gridInqYinc(gridID);
+
+      double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+
+      gridInqParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
       fprintf(gdp, "PDEF %d %d LCCR %g %g 1 1 %g %g %g %g %g\n",
-              xsize, ysize, originLat, originLon, lat1, lat2, lonParY, xincm, yincm);
+              xsize, ysize, xval_0, yval_0, lat_1, lat_2, lon_0, xinc, yinc);
 
       gridID = gridToCurvilinear(gridID, 0);
-      xvals = (double*) Malloc(xsize*ysize*sizeof(double));
-      yvals = (double*) Malloc(xsize*ysize*sizeof(double));
+      double *xvals = (double*) Malloc(xsize*ysize*sizeof(double));
+      double *yvals = (double*) Malloc(xsize*ysize*sizeof(double));
       gridInqXvals(gridID, xvals);
       gridInqYvals(gridID, yvals);
       for ( i = 0; i < xsize*ysize; ++i )
@@ -479,7 +479,7 @@ void ctl_xydef(FILE *gdp, int gridID, bool *yrev)
       xinc   = gridInqXinc(gridID);
       if ( IS_EQUAL(xinc, 0) && gridInqXvals(gridID, NULL) )
         {
-          xvals = (double*) Malloc(xsize*sizeof(double));
+          double *xvals = (double*) Malloc(xsize*sizeof(double));
           gridInqXvals(gridID, xvals);
           fprintf(gdp ,"XDEF %d LEVELS ", xsize);
           j = 0;
@@ -507,7 +507,7 @@ void ctl_xydef(FILE *gdp, int gridID, bool *yrev)
 
   /* YDEF */
 
-  if ( gridtype != GRID_LCC )
+  if ( ! (gridtype == GRID_PROJECTION && projtype == CDI_PROJ_LCC) )
     {
       yfirst = gridInqYval(gridID, 0);
       yinc   = gridInqYinc(gridID);
@@ -515,7 +515,7 @@ void ctl_xydef(FILE *gdp, int gridID, bool *yrev)
 
       if ( IS_EQUAL(yinc, 0) && gridInqYvals(gridID, NULL) )
         {
-          yvals = (double*) Malloc(ysize*sizeof(double));
+          double *yvals = (double*) Malloc(ysize*sizeof(double));
           gridInqYvals(gridID, yvals);
           fprintf(gdp ,"YDEF %d LEVELS ", ysize);
           j = 0;
@@ -1052,9 +1052,10 @@ void *Gradsdes(void *argument)
     {
       gridID = vlistGrid(vlistID, index);
       gridtype = gridInqType(gridID);
+      int projtype = gridInqProjType(gridID);
       if ( gridtype == GRID_LONLAT   ||
            gridtype == GRID_GAUSSIAN ||
-           gridtype == GRID_LCC  ) break;
+           (gridtype == GRID_PROJECTION && projtype == CDI_PROJ_LCC) ) break;
     }
 
   if ( index == ngrids )
diff --git a/src/Gridcell.c b/src/Gridcell.c
index c86ab6e..a141a74 100644
--- a/src/Gridcell.c
+++ b/src/Gridcell.c
@@ -49,7 +49,6 @@ void grid_cell_area(int gridID, double *array)
        projtype == CDI_PROJ_LAEA    ||
        projtype == CDI_PROJ_SINU    ||
        projtype == CDI_PROJ_LCC     ||
-       gridtype == GRID_LCC         ||
        gridtype == GRID_GME         ||
        gridtype == GRID_CURVILINEAR ||
        gridtype == GRID_UNSTRUCTURED )
@@ -193,9 +192,10 @@ void *Gridcell(void *argument)
   else if ( operatorID == GRIDDX || operatorID == GRIDDY )
     {
       int gridtype = gridInqType(gridID);
+      int projtype = (gridtype == GRID_PROJECTION) ? gridInqProjType(gridID) : -1;
       if ( gridtype == GRID_LONLAT      ||
 	   gridtype == GRID_GAUSSIAN    ||
-	   gridtype == GRID_LCC         ||
+           projtype == CDI_PROJ_LCC     ||
 	   gridtype == GRID_CURVILINEAR )
 	{
 	  double len1 = 0, len2 = 0;
diff --git a/src/Info.c b/src/Info.c
index f14adb4..7a0f488 100644
--- a/src/Info.c
+++ b/src/Info.c
@@ -239,33 +239,55 @@ void printMap(int nlon, int nlat, double *array, double missval, double min, dou
 }
 
 
+typedef struct {
+  double min, max, sum, sumi;
+  long nvals, nmiss, nlevs;
+} infostat_type;
+
+static
+void infostat_init(infostat_type *infostat)
+{
+  infostat->nvals = 0;
+  infostat->nmiss = 0;
+  infostat->nlevs = 0;
+  infostat->min =  DBL_MAX;
+  infostat->max = -DBL_MAX;
+  infostat->sum = 0;
+  infostat->sumi = 0;
+}
+
+
 void *Info(void *argument)
 {
+  enum {E_NAME, E_CODE, E_PARAM};
   int fpeRaised = 0;
   int varID, levelID;
   int nrecs;
   int nmiss;
-  int ivals = 0, nvals = 0;
-  int imiss = 0;
+  long imiss = 0;
   char varname[CDI_MAX_NAME];
   char paramstr[32];
   char vdatestr[32], vtimestr[32];
-  double arrmin = 0, arrmax = 0, arrmean = 0;
-  // double arrvar = 0;
 
   cdoInitialize(argument);
 
-  int INFO  = cdoOperatorAdd("info",  0, 0, NULL);
-  int INFOP = cdoOperatorAdd("infop", 0, 0, NULL);
-  int INFON = cdoOperatorAdd("infon", 0, 0, NULL);
-  int INFOC = cdoOperatorAdd("infoc", 0, 0, NULL);
-  int MAP   = cdoOperatorAdd("map",   0, 0, NULL);
+  int INFO   = cdoOperatorAdd("info",   E_PARAM,  0, NULL);
+  int INFOP  = cdoOperatorAdd("infop",  E_PARAM,  0, NULL);
+  int INFON  = cdoOperatorAdd("infon",  E_NAME,   0, NULL);
+  int INFOC  = cdoOperatorAdd("infoc",  E_CODE,   0, NULL);
+  int XINFON = cdoOperatorAdd("xinfon", E_NAME,   0, NULL);
+  int MAP    = cdoOperatorAdd("map",    E_PARAM,  0, NULL);
 
   UNUSED(INFO);
   UNUSED(INFOP);
+  UNUSED(INFON);
+  UNUSED(INFOC);
+  UNUSED(XINFON);
 
   int operatorID = cdoOperatorID();
 
+  int operfunc   = cdoOperatorF1(operatorID);
+
   dtlist_type *dtlist = dtlist_new();
 
   for ( int indf = 0; indf < cdoStreamCnt(); indf++ )
@@ -275,8 +297,11 @@ void *Info(void *argument)
       int vlistID = streamInqVlist(streamID);
       int taxisID = vlistInqTaxis(vlistID);
 
-      if ( vlistNvars(vlistID) == 0 ) continue;
+      int nvars = vlistNvars(vlistID);
+      if ( nvars == 0 ) continue;
 
+      infostat_type *infostat = (infostat_type*) Malloc(nvars*sizeof(infostat_type));
+                  
       int gridsizemax = vlistGridsizeMax(vlistID);
       if ( vlistNumber(vlistID) != CDI_REAL ) gridsizemax *= 2;
 
@@ -293,159 +318,189 @@ void *Info(void *argument)
 	  date2str(vdate, vdatestr, sizeof(vdatestr));
 	  time2str(vtime, vtimestr, sizeof(vtimestr));
 
-	  for ( int recID = 0; recID < nrecs; recID++ )
+          for ( varID = 0; varID < nvars; ++varID ) infostat_init(&infostat[varID]);
+
+	  for ( int recID = 0; recID < nrecs; ++recID )
 	    {
 	      if ( (tsID == 0 && recID == 0) || operatorID == MAP )
 		{
 		  set_text_color(stdout, BRIGHT, BLACK);
-		  fprintf(stdout, "%6d :       Date     Time   Level Gridsize    Miss :"
-			  "     Minimum        Mean     Maximum : ",  -(indf+1));
+		  fprintf(stdout, "%6d :       Date     Time   %s Gridsize    Miss :"
+			  "     Minimum        Mean     Maximum : ",  -(indf+1), operatorID==XINFON?"Nlevs":"Level");
 
-		  if      ( operatorID == INFON ) fprintf(stdout, "Parameter name");
-		  else if ( operatorID == INFOC ) fprintf(stdout, "Code number");
-		  else                            fprintf(stdout, "Parameter ID");
+		  if      ( operfunc == E_NAME ) fprintf(stdout, "Parameter name");
+		  else if ( operfunc == E_CODE ) fprintf(stdout, "Code number");
+		  else                           fprintf(stdout, "Parameter ID");
 
 		  if ( cdoVerbose ) fprintf(stdout, " : Extra" );
 		  reset_text_color(stdout);
-		  fprintf(stdout, "\n" );
+		  fprintf(stdout, "\n" );  
 		}
 
 	      streamInqRecord(streamID, &varID, &levelID);
 	      streamReadRecord(streamID, array, &nmiss);
 
-	      indg += 1;
+              infostat_type *infostatp = &infostat[varID];
+              indg = (operatorID == XINFON) ? varID+1 : indg + 1;
+              
 	      int param    = vlistInqVarParam(vlistID, varID);
 	      int code     = vlistInqVarCode(vlistID, varID);
 	      int gridID   = vlistInqVarGrid(vlistID, varID);
 	      int zaxisID  = vlistInqVarZaxis(vlistID, varID);
-	      int gridsize = gridInqSize(gridID);
 	      int number   = vlistInqVarNumber(vlistID, varID);
+	      long gridsize = gridInqSize(gridID);
+              long nlevs    = zaxisInqSize(zaxisID);
 	      double level = cdoZaxisInqLevel(zaxisID, levelID);
 	      double missval = vlistInqVarMissval(vlistID, varID);
+              
+              bool loutput = (operatorID != XINFON);
+                
+              if ( loutput ) infostat_init(infostatp);
 
-	      cdiParamToString(param, paramstr, sizeof(paramstr));
+              infostatp->nlevs += 1;
+              infostatp->nmiss += nmiss;
 
-	      if ( operatorID == INFON ) vlistInqVarName(vlistID, varID, varname);
+              if ( nlevs == infostatp->nlevs ) loutput = true;
 
-	      set_text_color(stdout, BRIGHT, BLACK);
-	      fprintf(stdout, "%6d ", indg);
-	      reset_text_color(stdout);
-	      set_text_color(stdout, RESET, BLACK);
-	      fprintf(stdout, ":");
-	      reset_text_color(stdout);
-	      
-              set_text_color(stdout, RESET, MAGENTA);
-	      fprintf(stdout, "%s %s ", vdatestr, vtimestr);
-	      reset_text_color(stdout);
+              if ( loutput )
+                {
+                  cdiParamToString(param, paramstr, sizeof(paramstr));
 
-	      set_text_color(stdout, RESET, GREEN);
-	      fprintf(stdout, "%7g ", level);
-	      fprintf(stdout, "%8d %7d ", gridsize, nmiss);
-		
-	      set_text_color(stdout, RESET, BLACK);
-	      fprintf(stdout, ":");
-	      reset_text_color(stdout);
+                  if ( operfunc == E_NAME ) vlistInqVarName(vlistID, varID, varname);
 
-              set_text_color(stdout, RESET, BLUE);
-	      if ( /* gridInqType(gridID) == GRID_SPECTRAL || */
-		   (gridsize == 1 && nmiss == 0 && number == CDI_REAL) )
-		{
-                  //fpeRaised = array_minmaxmean_val(gridsize, array, NULL, NULL, NULL);
-		  fprintf(stdout, "            %#12.5g            ", array[0]);
-		}
-	      else
-		{
-		  if ( number == CDI_REAL )
-		    {
-		      if ( nmiss > 0 )
-			{
-			  ivals   = 0;
-			  arrmean = 0;
-			  //arrvar  = 0;
-			  arrmin  =  1.e300;
-			  arrmax  = -1.e300;
-			  for ( int i = 0; i < gridsize; ++i )
-			    {
-			      if ( !DBL_IS_EQUAL(array[i], missval) )
-				{
-				  if ( array[i] < arrmin ) arrmin = array[i];
-				  if ( array[i] > arrmax ) arrmax = array[i];
-				  arrmean += array[i];
-				  //arrvar  += array[i]*array[i];
-				  ivals++;
-				}
-			    }
-                          fpeRaised = 0;
-			  imiss = gridsize - ivals;
-			  nvals = ivals;
-                          if ( nvals ) arrmean /= nvals;
-			}
-		      else
-			{
-                          fpeRaised = array_minmaxmean_val(gridsize, array, &arrmin, &arrmax, &arrmean);
-			  nvals = gridsize;
-			}
-
-		      if ( nvals )
-			{
-			  // arrvar  = arrvar/nvals - arrmean*arrmean;
-			  fprintf(stdout, "%#12.5g%#12.5g%#12.5g", arrmin, arrmean, arrmax);
-			}
-		      else
-			{
-			  fprintf(stdout, "                     nan            ");
-			}
-		    }
-		  else
-		    {
-		      int nvals_r = 0, nvals_i = 0;
-		      double arrsum_r, arrsum_i, arrmean_r = 0, arrmean_i = 0;
-		      arrsum_r = 0;
-		      arrsum_i = 0;
-		      
-		      for ( int i = 0; i < gridsize; i++ )
-			{
-			  if ( !DBL_IS_EQUAL(array[i*2],   missval) && 
-			       !DBL_IS_EQUAL(array[i*2+1], missval) )
-			    {
-			      arrsum_r += array[i*2];
-			      arrsum_i += array[i*2+1];
-			      nvals_r++;
-			      nvals_i++;
-			    }
-			}
-                      fpeRaised = 0;
-
-		      imiss = gridsize - nvals_r;
-
-		      if ( nvals_r > 0 ) arrmean_r = arrsum_r / nvals_r;
-		      if ( nvals_i > 0 ) arrmean_i = arrsum_i / nvals_i;
-		      fprintf(stdout, "   -  (%#12.5g,%#12.5g)  -", arrmean_r, arrmean_i);
-		    }
-		}
-	      reset_text_color(stdout);
-
-	      set_text_color(stdout, RESET, BLACK);
-	      fprintf(stdout, " : ");
-	      reset_text_color(stdout);
-
-	      set_text_color(stdout, BRIGHT, GREEN);
-	      if ( operatorID == INFON )
-		fprintf(stdout, "%-14s", varname);
-	      else if ( operatorID == INFOC )
-		fprintf(stdout, "%4d   ", code);
-	      else
-		fprintf(stdout, "%-14s", paramstr);
-	      reset_text_color(stdout);
-
-	      if ( cdoVerbose )
-		{
-		  char varextra[CDI_MAX_NAME];
-		  vlistInqVarExtra(vlistID, varID, varextra);
-		  fprintf(stdout, " : %s", varextra );              
-		}
-
-	      fprintf(stdout, "\n");
+                  set_text_color(stdout, BRIGHT, BLACK);
+                  fprintf(stdout, "%6d ", indg);
+                  reset_text_color(stdout);
+                  set_text_color(stdout, RESET, BLACK);
+                  fprintf(stdout, ":");
+                  reset_text_color(stdout);
+	      
+                  set_text_color(stdout, RESET, MAGENTA);
+                  fprintf(stdout, "%s %s ", vdatestr, vtimestr);
+                  reset_text_color(stdout);
+
+                  set_text_color(stdout, RESET, GREEN);
+                  if ( operatorID == XINFON )
+                    fprintf(stdout, "%7ld ", nlevs);
+                  else
+                    fprintf(stdout, "%7g ", level);
+                 
+                  fprintf(stdout, "%8ld %7ld ", gridsize, infostatp->nmiss);
+		
+                  set_text_color(stdout, RESET, BLACK);
+                  fprintf(stdout, ":");
+                  reset_text_color(stdout);
+
+                  set_text_color(stdout, RESET, BLUE);
+                }
+
+              if ( number == CDI_REAL )
+                {
+                  fpeRaised = 0;
+
+                  if ( infostatp->nmiss > 0 )
+                    {
+                      long nvals   = 0;
+                      for ( long i = 0; i < gridsize; ++i )
+                        {
+                          if ( !DBL_IS_EQUAL(array[i], missval) )
+                            {
+                              if ( array[i] < infostatp->min ) infostatp->min = array[i];
+                              if ( array[i] > infostatp->max ) infostatp->max = array[i];
+                              infostatp->sum += array[i];
+                              nvals++;
+                            }
+                        }
+                      imiss = gridsize - nvals;
+                      infostatp->nvals += nvals;
+                    }
+                  else if ( gridsize == 1 )
+                    {
+                      if ( infostatp->nvals == 0 )
+                        infostatp->sum = array[0];
+                      else
+                        infostatp->sum += array[0];
+                      infostatp->nvals += 1;
+                    }
+                  else
+                    {
+                      array_minmaxsum_val(gridsize, array, &infostatp->min, &infostatp->max, &infostatp->sum);
+                      infostatp->nvals += gridsize;
+                    }
+
+                  if ( loutput )
+                    {
+                      if ( infostatp->nvals )
+                        {
+                          if ( infostatp->nvals == 1 )
+                            {
+                              fprintf(stdout, "            %#12.5g            ", infostatp->sum);
+                            }
+                          else
+                            {
+                              double mean = infostatp->sum / (double)infostatp->nvals;
+                              fprintf(stdout, "%#12.5g%#12.5g%#12.5g", infostatp->min, mean, infostatp->max);
+                            }
+                        }
+                      else
+                        {
+                          fprintf(stdout, "                     nan            ");
+                        }
+                    }
+                }
+              else
+                {
+                  long nvals = 0;		      
+                  for ( long i = 0; i < gridsize; i++ )
+                    {
+                      if ( !DBL_IS_EQUAL(array[i*2],   missval) && 
+                           !DBL_IS_EQUAL(array[i*2+1], missval) )
+                        {
+                          infostatp->sum  += array[i*2];
+                          infostatp->sumi += array[i*2+1];
+                          nvals++;
+                        }
+                    }
+                  fpeRaised = 0;
+                  
+                  imiss = gridsize - nvals;
+                  infostatp->nvals += nvals;
+                          
+                  if ( loutput )
+                    {
+                      double arrmean_r = 0, arrmean_i = 0;
+                      if ( infostatp->nvals > 0 ) arrmean_r = infostatp->sum / infostatp->nvals;
+                      if ( infostatp->nvals > 0 ) arrmean_i = infostatp->sumi / infostatp->nvals;
+                      fprintf(stdout, "   -  (%#12.5g,%#12.5g)  -", arrmean_r, arrmean_i);
+                    }
+                }
+
+              if ( loutput )
+                {
+                  reset_text_color(stdout);
+
+                  set_text_color(stdout, RESET, BLACK);
+                  fprintf(stdout, " : ");
+                  reset_text_color(stdout);
+
+                  set_text_color(stdout, BRIGHT, GREEN);
+                  if ( operfunc == E_NAME )
+                    fprintf(stdout, "%-14s", varname);
+                  else if ( operfunc == E_CODE )
+                    fprintf(stdout, "%4d   ", code);
+                  else
+                    fprintf(stdout, "%-14s", paramstr);
+                  reset_text_color(stdout);
+                  
+                  if ( cdoVerbose )
+                    {
+                      char varextra[CDI_MAX_NAME];
+                      vlistInqVarExtra(vlistID, varID, varextra);
+                      fprintf(stdout, " : %s", varextra );              
+                    }
+
+                  fprintf(stdout, "\n");
+                }
 
 	      if ( imiss != nmiss && nmiss > 0 )
 		cdoPrint("Found %d of %d missing values!", imiss, nmiss);
@@ -463,7 +518,7 @@ void *Info(void *argument)
 		       (gridInqType(gridID) == GRID_GENERIC && 
 			nlon*nlat == gridInqSize(gridID) && nlon < 1024) )
 		    {
-		      printMap(nlon, nlat, array, missval, arrmin, arrmax);
+		      printMap(nlon, nlat, array, missval, infostatp->min, infostatp->max);
 		    }
 		}
 	    }
@@ -473,6 +528,7 @@ void *Info(void *argument)
       streamClose(streamID);
 
       if ( array ) Free(array);
+      if ( infostat ) Free(infostat);
     }
 
   dtlist_delete(dtlist);
diff --git a/src/Invert.c b/src/Invert.c
index 39f04d2..ab3e165 100644
--- a/src/Invert.c
+++ b/src/Invert.c
@@ -27,10 +27,8 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include "error.h"
 
 
 static
@@ -44,9 +42,9 @@ void invertLonDes(int vlistID)
 
       int gridtype = gridInqType(gridID1);
 
-      if ( gridtype != GRID_GENERIC && gridtype != GRID_GAUSSIAN &&
-	   gridtype != GRID_LONLAT  && gridtype != GRID_CURVILINEAR )
-	cdoAbort("Unsupported gridtype!");
+      if ( !(gridtype == GRID_GENERIC || gridtype == GRID_GAUSSIAN || gridtype == GRID_PROJECTION ||
+             gridtype == GRID_LONLAT  || gridtype == GRID_CURVILINEAR) )
+	cdoAbort("Unsupported gridtype: %s!", gridNamePtr(gridtype));
 
       if ( gridInqXvals(gridID1, NULL) )
 	{
@@ -116,6 +114,87 @@ void invertLonDes(int vlistID)
 }
 
 static
+void invertLatCoord(int gridID)
+{
+  int gridtype = gridInqType(gridID);
+
+  if ( gridInqYvals(gridID, NULL) )
+    {
+      int nlon = gridInqXsize(gridID);
+      int nlat = gridInqYsize(gridID);
+      int size = (gridtype == GRID_CURVILINEAR) ? nlon*nlat : nlat;
+
+      double *yv1 = (double*) Malloc(size*sizeof(double));
+      double *yv2 = (double*) Malloc(size*sizeof(double));
+
+      if ( gridtype == GRID_CURVILINEAR )
+        {
+          gridInqXvals(gridID, yv1);
+          
+          for ( int ilat = 0; ilat < nlat; ilat++ )
+            for ( int ilon = 0; ilon < nlon; ilon++ )
+              yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
+
+          gridDefXvals(gridID, yv2);
+          
+          gridInqYvals(gridID, yv1);
+
+          for ( int ilat = 0; ilat < nlat; ilat++ )
+            for ( int ilon = 0; ilon < nlon; ilon++ )
+              yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
+
+          gridDefYvals(gridID, yv2);
+        }
+      else
+        {
+          gridInqYvals(gridID, yv1);
+
+          for ( int ilat = 0; ilat < nlat; ilat++ )
+            yv2[nlat-ilat-1] = yv1[ilat];
+
+          gridDefYvals(gridID, yv2);
+        }
+
+      if ( yv2 ) Free(yv2);
+      if ( yv1 ) Free(yv1);
+    }
+
+  if ( gridInqYbounds(gridID, NULL) )
+    {
+      int nlon = gridInqXsize(gridID);
+      int nlat = gridInqYsize(gridID);
+      int nv   = gridInqNvertex(gridID);
+      int size = (gridtype == GRID_CURVILINEAR) ? nv*nlon*nlat : nv*nlat;
+
+      double *yb1 = (double*) Malloc(size*sizeof(double));
+      double *yb2 = (double*) Malloc(size*sizeof(double));
+
+      gridInqYbounds(gridID, yb1);
+
+      if ( gridtype == GRID_CURVILINEAR )
+        {
+          for ( int ilat = 0; ilat < nlat; ilat++ )
+            for ( int ilon = 0; ilon < nlon; ilon++ )
+              for ( int iv = 0; iv < nv; iv++ )
+                yb2[(nlat-ilat-1)*nlon*nv + ilon*nv + iv] = yb1[ilat*nlon*nv + ilon*nv + iv];
+        }
+      else
+        {
+          for ( int ilat = 0; ilat < nlat; ilat++ )
+            {
+              yb2[nlat*2-ilat*2-1] = yb1[ilat*2];
+              yb2[nlat*2-ilat*2-2] = yb1[ilat*2+1];
+            }
+        }
+
+      gridDefYbounds(gridID, yb2);
+
+      if ( yb2 ) Free(yb2);
+      if ( yb1 ) Free(yb1);
+    }
+}
+
+static
 void invertLatDes(int vlistID)
 {
   int ngrids = vlistNgrids(vlistID);
@@ -126,85 +205,14 @@ void invertLatDes(int vlistID)
 
       int gridtype = gridInqType(gridID1);
 
-      if ( gridtype != GRID_GENERIC && gridtype != GRID_GAUSSIAN &&
-	   gridtype != GRID_LONLAT  && gridtype != GRID_CURVILINEAR )
-	cdoAbort("Unsupported gridtype!");
-
-      if ( gridInqYvals(gridID1, NULL) )
-	{
-	  int nlon = gridInqXsize(gridID1);
-	  int nlat = gridInqYsize(gridID1);
-	  int size = (gridtype == GRID_CURVILINEAR) ? nlon*nlat : nlat;
-
-	  double *yv1 = (double*) Malloc(size*sizeof(double));
-	  double *yv2 = (double*) Malloc(size*sizeof(double));
-
-
-	  if ( gridtype == GRID_CURVILINEAR )
-	    {
-	      gridInqXvals(gridID1, yv1);
+      if ( !(gridtype == GRID_GENERIC || gridtype == GRID_GAUSSIAN || gridtype == GRID_PROJECTION ||
+             gridtype == GRID_LONLAT  || gridtype == GRID_CURVILINEAR) )
+	cdoAbort("Unsupported gridtype: %s!", gridNamePtr(gridtype));
 
-	      for ( int ilat = 0; ilat < nlat; ilat++ )
-		for ( int ilon = 0; ilon < nlon; ilon++ )
-		  yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
-
-	      gridDefXvals(gridID2, yv2);
-
-	      gridInqYvals(gridID1, yv1);
+      invertLatCoord(gridID2);
 
-	      for ( int ilat = 0; ilat < nlat; ilat++ )
-		for ( int ilon = 0; ilon < nlon; ilon++ )
-		  yv2[(nlat-ilat-1)*nlon + ilon] = yv1[ilat*nlon + ilon];
-
-	      gridDefYvals(gridID2, yv2);
-	    }
-	  else
-	    {
-	      gridInqYvals(gridID1, yv1);
-
-	      for ( int ilat = 0; ilat < nlat; ilat++ )
-		yv2[nlat-ilat-1] = yv1[ilat];
-
-	      gridDefYvals(gridID2, yv2);
-	    }
-
-	  if ( yv2 ) Free(yv2);
-	  if ( yv1 ) Free(yv1);
-	}
-
-      if ( gridInqYbounds(gridID1, NULL) )
-	{
-	  int nlon = gridInqXsize(gridID1);
-	  int nlat = gridInqYsize(gridID1);
-	  int nv   = gridInqNvertex(gridID1);
-	  int size = (gridtype == GRID_CURVILINEAR) ? nv*nlon*nlat : nv*nlat;
-
-	  double *yb1 = (double*) Malloc(size*sizeof(double));
-	  double *yb2 = (double*) Malloc(size*sizeof(double));
-
-	  gridInqYbounds(gridID1, yb1);
-
-	  if ( gridtype == GRID_CURVILINEAR )
-	    {
-	      for ( int ilat = 0; ilat < nlat; ilat++ )
-		for ( int ilon = 0; ilon < nlon; ilon++ )
-		  for ( int iv = 0; iv < nv; iv++ )
-		    yb2[(nlat-ilat-1)*nlon*nv + ilon*nv + iv] = yb1[ilat*nlon*nv + ilon*nv + iv];
-	    }
-	  else
-	    {
-		for ( int ilat = 0; ilat < nlat; ilat++ )
-		  {
-		    yb2[nlat*2-ilat*2-1] = yb1[ilat*2];
-		    yb2[nlat*2-ilat*2-2] = yb1[ilat*2+1];
-		  }
-	    }
-
-	  gridDefYbounds(gridID2, yb2);
-
-	  if ( yb2 ) Free(yb2);
-	  if ( yb1 ) Free(yb1);
-	}
+      int projID = gridInqProj(gridID2);
+      if ( projID != CDI_UNDEFID ) invertLatCoord(projID);
 
       vlistChangeGrid(vlistID, gridID1, gridID2);
     }
@@ -301,10 +309,8 @@ void *Invert(void *argument)
 
   if ( operfunc1 == func_all || operfunc1 == func_hrd )
     {
-      if ( operfunc2 == func_lat )
-	invertLatDes(vlistID2);
-      else
-	invertLonDes(vlistID2);
+      if ( operfunc2 == func_lat ) invertLatDes(vlistID2);
+      else                         invertLonDes(vlistID2);
     }
 
   int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
diff --git a/src/Invertlev.c b/src/Invertlev.c
index 068f4a8..4a11ad7 100644
--- a/src/Invertlev.c
+++ b/src/Invertlev.c
@@ -22,10 +22,8 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include "error.h"
 
 
 static
diff --git a/src/Makefile.am b/src/Makefile.am
index 08a87de..4b7b957 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,6 +12,7 @@ libcdo_la_SOURCES =            \
                cdo_task.c      \
                cdo_task.h      \
                cdo_history.c   \
+               cdo_read.c      \
                cdi_uuid.h      \
                cmortable_parser.c   \
                after_sptrans.c \
@@ -65,9 +66,11 @@ libcdo_la_SOURCES =            \
                gradsdeslib.h   \
                grid.c          \
                grid.h          \
+               grid_proj.c     \
+               grid_proj.h     \
                grid_area.c     \
+               grid_define.c   \
                grid_gme.c      \
-               grid_lcc.c      \
                grid_rot.c      \
                grid_from_name.c   \
                grid_read.c        \
@@ -299,12 +302,14 @@ cdo_SOURCES += Adisit.c        \
                Rotuv.c         \
                Runpctl.c       \
                Runstat.c       \
+               Samplegrid.c    \
                Seascount.c     \
                Seaspctl.c      \
                Seasstat.c      \
                Selbox.c        \
-               Selindex.c      \
+               Selgridcell.c   \
                Select.c        \
+               Selmulti.c      \
                Seloperator.c   \
                Selrec.c        \
                Seltime.c       \
@@ -364,6 +369,7 @@ cdo_SOURCES += Adisit.c        \
                Verifygrid.c    \
                Wct.c           \
                Wind.c          \
+               WindTrans.c     \
                Writegrid.c     \
                Writerandom.c   \
                XTimstat.c      \
diff --git a/src/Makefile.in b/src/Makefile.in
index c17641c..944b306 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -105,21 +105,22 @@ am__dirstamp = $(am__leading_dot)dirstamp
 am_libcdo_la_OBJECTS = libcdo_la-array.lo libcdo_la-cdo_pthread.lo \
 	libcdo_la-cdo_vlist.lo libcdo_la-cdo_getopt.lo \
 	libcdo_la-cdo_task.lo libcdo_la-cdo_history.lo \
-	libcdo_la-cmortable_parser.lo libcdo_la-after_sptrans.lo \
-	libcdo_la-after_fctrans.lo libcdo_la-after_dvtrans.lo \
-	libcdo_la-after_vertint.lo libcdo_la-after_namelist.lo \
-	libcdo_la-afterburnerlib.lo libcdo_la-constants.lo \
-	libcdo_la-color.lo libcdo_la-commandline.lo \
-	libcdo_la-convert_units.lo libcdo_la-datetime.lo \
-	libcdo_la-ecacore.lo libcdo_la-ecautil.lo \
-	libcdo_la-exception.lo libcdo_la-expr.lo libcdo_la-expr_fun.lo \
-	libcdo_la-expr_lex.lo libcdo_la-expr_yacc.lo \
-	libcdo_la-features.lo libcdo_la-field.lo libcdo_la-field2.lo \
-	libcdo_la-fieldc.lo libcdo_la-fieldmem.lo \
-	libcdo_la-fieldmer.lo libcdo_la-fieldzon.lo \
-	libcdo_la-gradsdeslib.lo libcdo_la-grid.lo \
-	libcdo_la-grid_area.lo libcdo_la-grid_gme.lo \
-	libcdo_la-grid_lcc.lo libcdo_la-grid_rot.lo \
+	libcdo_la-cdo_read.lo libcdo_la-cmortable_parser.lo \
+	libcdo_la-after_sptrans.lo libcdo_la-after_fctrans.lo \
+	libcdo_la-after_dvtrans.lo libcdo_la-after_vertint.lo \
+	libcdo_la-after_namelist.lo libcdo_la-afterburnerlib.lo \
+	libcdo_la-constants.lo libcdo_la-color.lo \
+	libcdo_la-commandline.lo libcdo_la-convert_units.lo \
+	libcdo_la-datetime.lo libcdo_la-ecacore.lo \
+	libcdo_la-ecautil.lo libcdo_la-exception.lo libcdo_la-expr.lo \
+	libcdo_la-expr_fun.lo libcdo_la-expr_lex.lo \
+	libcdo_la-expr_yacc.lo libcdo_la-features.lo \
+	libcdo_la-field.lo libcdo_la-field2.lo libcdo_la-fieldc.lo \
+	libcdo_la-fieldmem.lo libcdo_la-fieldmer.lo \
+	libcdo_la-fieldzon.lo libcdo_la-gradsdeslib.lo \
+	libcdo_la-grid.lo libcdo_la-grid_proj.lo \
+	libcdo_la-grid_area.lo libcdo_la-grid_define.lo \
+	libcdo_la-grid_gme.lo libcdo_la-grid_rot.lo \
 	libcdo_la-grid_from_name.lo libcdo_la-grid_read.lo \
 	libcdo_la-grid_read_pingo.lo libcdo_la-grid_print.lo \
 	libcdo_la-gridreference.lo libcdo_la-griddes.lo \
@@ -215,10 +216,11 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-Remap.$(OBJEXT) cdo-Remapeta.$(OBJEXT) \
 	cdo-Replace.$(OBJEXT) cdo-Replacevalues.$(OBJEXT) \
 	cdo-Rhopot.$(OBJEXT) cdo-Rotuv.$(OBJEXT) cdo-Runpctl.$(OBJEXT) \
-	cdo-Runstat.$(OBJEXT) cdo-Seascount.$(OBJEXT) \
-	cdo-Seaspctl.$(OBJEXT) cdo-Seasstat.$(OBJEXT) \
-	cdo-Selbox.$(OBJEXT) cdo-Selindex.$(OBJEXT) \
-	cdo-Select.$(OBJEXT) cdo-Seloperator.$(OBJEXT) \
+	cdo-Runstat.$(OBJEXT) cdo-Samplegrid.$(OBJEXT) \
+	cdo-Seascount.$(OBJEXT) cdo-Seaspctl.$(OBJEXT) \
+	cdo-Seasstat.$(OBJEXT) cdo-Selbox.$(OBJEXT) \
+	cdo-Selgridcell.$(OBJEXT) cdo-Select.$(OBJEXT) \
+	cdo-Selmulti.$(OBJEXT) cdo-Seloperator.$(OBJEXT) \
 	cdo-Selrec.$(OBJEXT) cdo-Seltime.$(OBJEXT) \
 	cdo-Selvar.$(OBJEXT) cdo-Set.$(OBJEXT) \
 	cdo-Setattribute.$(OBJEXT) cdo-Setbox.$(OBJEXT) \
@@ -246,17 +248,18 @@ am_cdo_OBJECTS = cdo-cdo.$(OBJEXT) cdo-Adisit.$(OBJEXT) \
 	cdo-Vertintap.$(OBJEXT) cdo-Vertstat.$(OBJEXT) \
 	cdo-Vertcum.$(OBJEXT) cdo-Vertwind.$(OBJEXT) \
 	cdo-Verifygrid.$(OBJEXT) cdo-Wct.$(OBJEXT) cdo-Wind.$(OBJEXT) \
-	cdo-Writegrid.$(OBJEXT) cdo-Writerandom.$(OBJEXT) \
-	cdo-XTimstat.$(OBJEXT) cdo-YAR.$(OBJEXT) \
-	cdo-Yearmonstat.$(OBJEXT) cdo-Ydayarith.$(OBJEXT) \
-	cdo-Ydaypctl.$(OBJEXT) cdo-Ydaystat.$(OBJEXT) \
-	cdo-Ydrunpctl.$(OBJEXT) cdo-Ydrunstat.$(OBJEXT) \
-	cdo-Yhourarith.$(OBJEXT) cdo-Yhourstat.$(OBJEXT) \
-	cdo-Ymonarith.$(OBJEXT) cdo-Ymonpctl.$(OBJEXT) \
-	cdo-Ymonstat.$(OBJEXT) cdo-Yseaspctl.$(OBJEXT) \
-	cdo-Yseasstat.$(OBJEXT) cdo-Zonstat.$(OBJEXT) \
-	cdo-Magplot.$(OBJEXT) cdo-Magvector.$(OBJEXT) \
-	cdo-Maggraph.$(OBJEXT) cdo-template_parser.$(OBJEXT) \
+	cdo-WindTrans.$(OBJEXT) cdo-Writegrid.$(OBJEXT) \
+	cdo-Writerandom.$(OBJEXT) cdo-XTimstat.$(OBJEXT) \
+	cdo-YAR.$(OBJEXT) cdo-Yearmonstat.$(OBJEXT) \
+	cdo-Ydayarith.$(OBJEXT) cdo-Ydaypctl.$(OBJEXT) \
+	cdo-Ydaystat.$(OBJEXT) cdo-Ydrunpctl.$(OBJEXT) \
+	cdo-Ydrunstat.$(OBJEXT) cdo-Yhourarith.$(OBJEXT) \
+	cdo-Yhourstat.$(OBJEXT) cdo-Ymonarith.$(OBJEXT) \
+	cdo-Ymonpctl.$(OBJEXT) cdo-Ymonstat.$(OBJEXT) \
+	cdo-Yseaspctl.$(OBJEXT) cdo-Yseasstat.$(OBJEXT) \
+	cdo-Zonstat.$(OBJEXT) cdo-Magplot.$(OBJEXT) \
+	cdo-Magvector.$(OBJEXT) cdo-Maggraph.$(OBJEXT) \
+	cdo-template_parser.$(OBJEXT) \
 	cdo-results_template_parser.$(OBJEXT) \
 	cdo-magics_template_parser.$(OBJEXT) \
 	cdo-StringUtilities.$(OBJEXT) cdo-CdoMagicsMapper.$(OBJEXT)
@@ -343,6 +346,7 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BASH = @BASH@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -508,21 +512,22 @@ top_srcdir = @top_srcdir@
 noinst_LTLIBRARIES = libcdo.la
 libcdo_la_SOURCES = array.h array.c cdo_int.h compare.h cdo_pthread.c \
 	cdo_vlist.c cdo_getopt.c cdo_getopt.h cdo_task.c cdo_task.h \
-	cdo_history.c cdi_uuid.h cmortable_parser.c after_sptrans.c \
-	after_fctrans.c after_dvtrans.c after_vertint.c \
-	after_vertint.h after_namelist.c afterburnerlib.c \
-	afterburner.h vct_l191.h calendar.h constants.h constants.c \
-	color.c color.h commandline.c const.h convert_units.c \
-	convert_units.h counter.h datetime.c datetime.h dmemory.h \
-	ecacore.c ecacore.h ecautil.c ecautil.h error.h etopo.h temp.h \
-	mask.h exception.c expr.c expr.h expr_fun.c expr_fun.h \
-	expr_lex.c expr_yacc.c expr_yacc.h features.c field.c field.h \
-	field2.c fieldc.c fieldmem.c fieldmer.c fieldzon.c functs.h \
-	gradsdeslib.c gradsdeslib.h grid.c grid.h grid_area.c \
-	grid_gme.c grid_lcc.c grid_rot.c grid_from_name.c grid_read.c \
-	grid_read_pingo.c grid_print.c gridreference.c griddes.c \
-	griddes.h griddes_h5.c griddes_nc.c hetaeta.c hetaeta.h \
-	institution.c interpol.c interpol.h job.c juldate.c \
+	cdo_history.c cdo_read.c cdi_uuid.h cmortable_parser.c \
+	after_sptrans.c after_fctrans.c after_dvtrans.c \
+	after_vertint.c after_vertint.h after_namelist.c \
+	afterburnerlib.c afterburner.h vct_l191.h calendar.h \
+	constants.h constants.c color.c color.h commandline.c const.h \
+	convert_units.c convert_units.h counter.h datetime.c \
+	datetime.h dmemory.h ecacore.c ecacore.h ecautil.c ecautil.h \
+	error.h etopo.h temp.h mask.h exception.c expr.c expr.h \
+	expr_fun.c expr_fun.h expr_lex.c expr_yacc.c expr_yacc.h \
+	features.c field.c field.h field2.c fieldc.c fieldmem.c \
+	fieldmer.c fieldzon.c functs.h gradsdeslib.c gradsdeslib.h \
+	grid.c grid.h grid_proj.c grid_proj.h grid_area.c \
+	grid_define.c grid_gme.c grid_rot.c grid_from_name.c \
+	grid_read.c grid_read_pingo.c grid_print.c gridreference.c \
+	griddes.c griddes.h griddes_h5.c griddes_nc.c hetaeta.c \
+	hetaeta.h institution.c interpol.c interpol.h job.c juldate.c \
 	grid_search.c grid_search.h listarray.c listarray.h list.c \
 	list.h listbuf.c listbuf.h merge_sort2.c merge_sort2.h \
 	modules.c modules.h namelist.c namelist.h namelist_parser.c \
@@ -579,26 +584,28 @@ cdo_SOURCES = cdo.c Adisit.c Afterburner.c Arith.c Arithc.c \
 	Mrotuv.c Mrotuvb.c Ninfo.c Nmldump.c Output.c Outputgmt.c \
 	Pack.c Pardup.c Pinfo.c Pressure.c Regres.c Remap.c Remapeta.c \
 	Replace.c Replacevalues.c Rhopot.c Rotuv.c Runpctl.c Runstat.c \
-	Seascount.c Seaspctl.c Seasstat.c Selbox.c Selindex.c Select.c \
-	Seloperator.c Selrec.c Seltime.c Selvar.c Set.c Setattribute.c \
-	Setbox.c Setgatt.c Setgrid.c Sethalo.c Setmiss.c Setpartab.c \
-	Setrcaname.c Settime.c Setzaxis.c Shiftxy.c Showinfo.c Sinfo.c \
-	Smooth.c Sort.c Sorttimestamp.c Specinfo.c Spectral.c \
-	Spectrum.c Split.c Splitrec.c Splitsel.c Splittime.c \
-	Splityear.c Subtrend.c Tee.c Templates.c Test.c Tests.c \
-	Timcount.c Timcumsum.c Timpctl.c Timselpctl.c Timselstat.c \
-	Timsort.c Timstat.c Timstat2.c Timstat3.c Tinfo.c Tocomplex.c \
+	Samplegrid.c Seascount.c Seaspctl.c Seasstat.c Selbox.c \
+	Selgridcell.c Select.c Selmulti.c Seloperator.c Selrec.c \
+	Seltime.c Selvar.c Set.c Setattribute.c Setbox.c Setgatt.c \
+	Setgrid.c Sethalo.c Setmiss.c Setpartab.c Setrcaname.c \
+	Settime.c Setzaxis.c Shiftxy.c Showinfo.c Sinfo.c Smooth.c \
+	Sort.c Sorttimestamp.c Specinfo.c Spectral.c Spectrum.c \
+	Split.c Splitrec.c Splitsel.c Splittime.c Splityear.c \
+	Subtrend.c Tee.c Templates.c Test.c Tests.c Timcount.c \
+	Timcumsum.c Timpctl.c Timselpctl.c Timselstat.c Timsort.c \
+	Timstat.c Timstat2.c Timstat3.c Tinfo.c Tocomplex.c \
 	Transpose.c Trend.c Trms.c Tstepcount.c Vargen.c Varrms.c \
 	Vertintml.c Vertintap.c Vertstat.c Vertcum.c Vertwind.c \
-	Verifygrid.c Wct.c Wind.c Writegrid.c Writerandom.c XTimstat.c \
-	YAR.c Yearmonstat.c Ydayarith.c Ydaypctl.c Ydaystat.c \
-	Ydrunpctl.c Ydrunstat.c Yhourarith.c Yhourstat.c Ymonarith.c \
-	Ymonpctl.c Ymonstat.c Yseaspctl.c Yseasstat.c Zonstat.c cdo.h \
-	nearpt3c.h Magplot.c Magvector.c Maggraph.c template_parser.h \
-	template_parser.c results_template_parser.h \
-	results_template_parser.c magics_template_parser.h \
-	magics_template_parser.c StringUtilities.h StringUtilities.c \
-	CdoMagicsMapper.h CdoMagicsMapper.c
+	Verifygrid.c Wct.c Wind.c WindTrans.c Writegrid.c \
+	Writerandom.c XTimstat.c YAR.c Yearmonstat.c Ydayarith.c \
+	Ydaypctl.c Ydaystat.c Ydrunpctl.c Ydrunstat.c Yhourarith.c \
+	Yhourstat.c Ymonarith.c Ymonpctl.c Ymonstat.c Yseaspctl.c \
+	Yseasstat.c Zonstat.c cdo.h nearpt3c.h Magplot.c Magvector.c \
+	Maggraph.c template_parser.h template_parser.c \
+	results_template_parser.h results_template_parser.c \
+	magics_template_parser.h magics_template_parser.c \
+	StringUtilities.h StringUtilities.c CdoMagicsMapper.h \
+	CdoMagicsMapper.c
 #endif
 cdo_CPPFLAGS = -I$(top_srcdir)/libcdi/src
 cdo_LDADD = libcdo.la $(top_builddir)/libcdi/src/libcdi.la
@@ -914,12 +921,14 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Rotuv.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Runpctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Runstat.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Samplegrid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seascount.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seaspctl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seasstat.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Selbox.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Select.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Selindex.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Selgridcell.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Selmulti.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seloperator.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Selrec.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Seltime.Po at am__quote@
@@ -980,6 +989,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Vertwind.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Wct.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Wind.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-WindTrans.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Writegrid.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-Writerandom.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/cdo-XTimstat.Po at am__quote@
@@ -1013,6 +1023,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_getopt.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_history.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_pthread.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_read.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_task.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cdo_vlist.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-cmortable_parser.Plo at am__quote@
@@ -1038,10 +1049,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-gradsdeslib.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_area.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_define.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_from_name.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_gme.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_lcc.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_print.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_proj.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_read.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_read_pingo.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libcdo_la-grid_rot.Plo at am__quote@
@@ -1178,6 +1190,13 @@ libcdo_la-cdo_history.lo: cdo_history.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-cdo_history.lo `test -f 'cdo_history.c' || echo '$(srcdir)/'`cdo_history.c
 
+libcdo_la-cdo_read.lo: cdo_read.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-cdo_read.lo -MD -MP -MF $(DEPDIR)/libcdo_la-cdo_read.Tpo -c -o libcdo_la-cdo_read.lo `test -f 'cdo_read.c' || echo '$(srcdir)/'`cdo_read.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-cdo_read.Tpo $(DEPDIR)/libcdo_la-cdo_read.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='cdo_read.c' object='libcdo_la-cdo_read.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-cdo_read.lo `test -f 'cdo_read.c' || echo '$(srcdir)/'`cdo_read.c
+
 libcdo_la-cmortable_parser.lo: cmortable_parser.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-cmortable_parser.lo -MD -MP -MF $(DEPDIR)/libcdo_la-cmortable_parser.Tpo -c -o libcdo_la-cmortable_parser.lo `test -f 'cmortable_parser.c' || echo '$(srcdir)/'`cmortable_parser.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-cmortable_parser.Tpo $(DEPDIR)/libcdo_la-cmortable_parser.Plo
@@ -1374,6 +1393,13 @@ libcdo_la-grid.lo: grid.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid.lo `test -f 'grid.c' || echo '$(srcdir)/'`grid.c
 
+libcdo_la-grid_proj.lo: grid_proj.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_proj.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_proj.Tpo -c -o libcdo_la-grid_proj.lo `test -f 'grid_proj.c' || echo '$(srcdir)/'`grid_proj.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_proj.Tpo $(DEPDIR)/libcdo_la-grid_proj.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='grid_proj.c' object='libcdo_la-grid_proj.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid_proj.lo `test -f 'grid_proj.c' || echo '$(srcdir)/'`grid_proj.c
+
 libcdo_la-grid_area.lo: grid_area.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_area.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_area.Tpo -c -o libcdo_la-grid_area.lo `test -f 'grid_area.c' || echo '$(srcdir)/'`grid_area.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_area.Tpo $(DEPDIR)/libcdo_la-grid_area.Plo
@@ -1381,6 +1407,13 @@ libcdo_la-grid_area.lo: grid_area.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid_area.lo `test -f 'grid_area.c' || echo '$(srcdir)/'`grid_area.c
 
+libcdo_la-grid_define.lo: grid_define.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_define.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_define.Tpo -c -o libcdo_la-grid_define.lo `test -f 'grid_define.c' || echo '$(srcdir)/'`grid_define.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_define.Tpo $(DEPDIR)/libcdo_la-grid_define.Plo
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='grid_define.c' object='libcdo_la-grid_define.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid_define.lo `test -f 'grid_define.c' || echo '$(srcdir)/'`grid_define.c
+
 libcdo_la-grid_gme.lo: grid_gme.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_gme.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_gme.Tpo -c -o libcdo_la-grid_gme.lo `test -f 'grid_gme.c' || echo '$(srcdir)/'`grid_gme.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_gme.Tpo $(DEPDIR)/libcdo_la-grid_gme.Plo
@@ -1388,13 +1421,6 @@ libcdo_la-grid_gme.lo: grid_gme.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid_gme.lo `test -f 'grid_gme.c' || echo '$(srcdir)/'`grid_gme.c
 
-libcdo_la-grid_lcc.lo: grid_lcc.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_lcc.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_lcc.Tpo -c -o libcdo_la-grid_lcc.lo `test -f 'grid_lcc.c' || echo '$(srcdir)/'`grid_lcc.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_lcc.Tpo $(DEPDIR)/libcdo_la-grid_lcc.Plo
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='grid_lcc.c' object='libcdo_la-grid_lcc.lo' libtool=yes @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libcdo_la-grid_lcc.lo `test -f 'grid_lcc.c' || echo '$(srcdir)/'`grid_lcc.c
-
 libcdo_la-grid_rot.lo: grid_rot.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcdo_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libcdo_la-grid_rot.lo -MD -MP -MF $(DEPDIR)/libcdo_la-grid_rot.Tpo -c -o libcdo_la-grid_rot.lo `test -f 'grid_rot.c' || echo '$(srcdir)/'`grid_rot.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/libcdo_la-grid_rot.Tpo $(DEPDIR)/libcdo_la-grid_rot.Plo
@@ -3390,6 +3416,20 @@ cdo-Runstat.obj: Runstat.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Runstat.obj `if test -f 'Runstat.c'; then $(CYGPATH_W) 'Runstat.c'; else $(CYGPATH_W) '$(srcdir)/Runstat.c'; fi`
 
+cdo-Samplegrid.o: Samplegrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Samplegrid.o -MD -MP -MF $(DEPDIR)/cdo-Samplegrid.Tpo -c -o cdo-Samplegrid.o `test -f 'Samplegrid.c' || echo '$(srcdir)/'`Samplegrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Samplegrid.Tpo $(DEPDIR)/cdo-Samplegrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Samplegrid.c' object='cdo-Samplegrid.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Samplegrid.o `test -f 'Samplegrid.c' || echo '$(srcdir)/'`Samplegrid.c
+
+cdo-Samplegrid.obj: Samplegrid.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Samplegrid.obj -MD -MP -MF $(DEPDIR)/cdo-Samplegrid.Tpo -c -o cdo-Samplegrid.obj `if test -f 'Samplegrid.c'; then $(CYGPATH_W) 'Samplegrid.c'; else $(CYGPATH_W) '$(srcdir)/Samplegrid.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Samplegrid.Tpo $(DEPDIR)/cdo-Samplegrid.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Samplegrid.c' object='cdo-Samplegrid.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Samplegrid.obj `if test -f 'Samplegrid.c'; then $(CYGPATH_W) 'Samplegrid.c'; else $(CYGPATH_W) '$(srcdir)/Samplegrid.c'; fi`
+
 cdo-Seascount.o: Seascount.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Seascount.o -MD -MP -MF $(DEPDIR)/cdo-Seascount.Tpo -c -o cdo-Seascount.o `test -f 'Seascount.c' || echo '$(srcdir)/'`Seascount.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Seascount.Tpo $(DEPDIR)/cdo-Seascount.Po
@@ -3446,19 +3486,19 @@ cdo-Selbox.obj: Selbox.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selbox.obj `if test -f 'Selbox.c'; then $(CYGPATH_W) 'Selbox.c'; else $(CYGPATH_W) '$(srcdir)/Selbox.c'; fi`
 
-cdo-Selindex.o: Selindex.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selindex.o -MD -MP -MF $(DEPDIR)/cdo-Selindex.Tpo -c -o cdo-Selindex.o `test -f 'Selindex.c' || echo '$(srcdir)/'`Selindex.c
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selindex.Tpo $(DEPDIR)/cdo-Selindex.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selindex.c' object='cdo-Selindex.o' libtool=no @AMDEPBACKSLASH@
+cdo-Selgridcell.o: Selgridcell.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selgridcell.o -MD -MP -MF $(DEPDIR)/cdo-Selgridcell.Tpo -c -o cdo-Selgridcell.o `test -f 'Selgridcell.c' || echo '$(srcdir)/'`Selgridcell.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selgridcell.Tpo $(DEPDIR)/cdo-Selgridcell.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selgridcell.c' object='cdo-Selgridcell.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selindex.o `test -f 'Selindex.c' || echo '$(srcdir)/'`Selindex.c
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selgridcell.o `test -f 'Selgridcell.c' || echo '$(srcdir)/'`Selgridcell.c
 
-cdo-Selindex.obj: Selindex.c
- at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selindex.obj -MD -MP -MF $(DEPDIR)/cdo-Selindex.Tpo -c -o cdo-Selindex.obj `if test -f 'Selindex.c'; then $(CYGPATH_W) 'Selindex.c'; else $(CYGPATH_W) '$(srcdir)/Selindex.c'; fi`
- at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selindex.Tpo $(DEPDIR)/cdo-Selindex.Po
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selindex.c' object='cdo-Selindex.obj' libtool=no @AMDEPBACKSLASH@
+cdo-Selgridcell.obj: Selgridcell.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selgridcell.obj -MD -MP -MF $(DEPDIR)/cdo-Selgridcell.Tpo -c -o cdo-Selgridcell.obj `if test -f 'Selgridcell.c'; then $(CYGPATH_W) 'Selgridcell.c'; else $(CYGPATH_W) '$(srcdir)/Selgridcell.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selgridcell.Tpo $(DEPDIR)/cdo-Selgridcell.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selgridcell.c' object='cdo-Selgridcell.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selindex.obj `if test -f 'Selindex.c'; then $(CYGPATH_W) 'Selindex.c'; else $(CYGPATH_W) '$(srcdir)/Selindex.c'; fi`
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selgridcell.obj `if test -f 'Selgridcell.c'; then $(CYGPATH_W) 'Selgridcell.c'; else $(CYGPATH_W) '$(srcdir)/Selgridcell.c'; fi`
 
 cdo-Select.o: Select.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Select.o -MD -MP -MF $(DEPDIR)/cdo-Select.Tpo -c -o cdo-Select.o `test -f 'Select.c' || echo '$(srcdir)/'`Select.c
@@ -3474,6 +3514,20 @@ cdo-Select.obj: Select.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Select.obj `if test -f 'Select.c'; then $(CYGPATH_W) 'Select.c'; else $(CYGPATH_W) '$(srcdir)/Select.c'; fi`
 
+cdo-Selmulti.o: Selmulti.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selmulti.o -MD -MP -MF $(DEPDIR)/cdo-Selmulti.Tpo -c -o cdo-Selmulti.o `test -f 'Selmulti.c' || echo '$(srcdir)/'`Selmulti.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selmulti.Tpo $(DEPDIR)/cdo-Selmulti.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selmulti.c' object='cdo-Selmulti.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selmulti.o `test -f 'Selmulti.c' || echo '$(srcdir)/'`Selmulti.c
+
+cdo-Selmulti.obj: Selmulti.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Selmulti.obj -MD -MP -MF $(DEPDIR)/cdo-Selmulti.Tpo -c -o cdo-Selmulti.obj `if test -f 'Selmulti.c'; then $(CYGPATH_W) 'Selmulti.c'; else $(CYGPATH_W) '$(srcdir)/Selmulti.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Selmulti.Tpo $(DEPDIR)/cdo-Selmulti.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='Selmulti.c' object='cdo-Selmulti.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Selmulti.obj `if test -f 'Selmulti.c'; then $(CYGPATH_W) 'Selmulti.c'; else $(CYGPATH_W) '$(srcdir)/Selmulti.c'; fi`
+
 cdo-Seloperator.o: Seloperator.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Seloperator.o -MD -MP -MF $(DEPDIR)/cdo-Seloperator.Tpo -c -o cdo-Seloperator.o `test -f 'Seloperator.c' || echo '$(srcdir)/'`Seloperator.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Seloperator.Tpo $(DEPDIR)/cdo-Seloperator.Po
@@ -4300,6 +4354,20 @@ cdo-Wind.obj: Wind.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-Wind.obj `if test -f 'Wind.c'; then $(CYGPATH_W) 'Wind.c'; else $(CYGPATH_W) '$(srcdir)/Wind.c'; fi`
 
+cdo-WindTrans.o: WindTrans.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-WindTrans.o -MD -MP -MF $(DEPDIR)/cdo-WindTrans.Tpo -c -o cdo-WindTrans.o `test -f 'WindTrans.c' || echo '$(srcdir)/'`WindTrans.c
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-WindTrans.Tpo $(DEPDIR)/cdo-WindTrans.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='WindTrans.c' object='cdo-WindTrans.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-WindTrans.o `test -f 'WindTrans.c' || echo '$(srcdir)/'`WindTrans.c
+
+cdo-WindTrans.obj: WindTrans.c
+ at am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-WindTrans.obj -MD -MP -MF $(DEPDIR)/cdo-WindTrans.Tpo -c -o cdo-WindTrans.obj `if test -f 'WindTrans.c'; then $(CYGPATH_W) 'WindTrans.c'; else $(CYGPATH_W) '$(srcdir)/WindTrans.c'; fi`
+ at am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-WindTrans.Tpo $(DEPDIR)/cdo-WindTrans.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='WindTrans.c' object='cdo-WindTrans.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(AM_V_CC at am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cdo-WindTrans.obj `if test -f 'WindTrans.c'; then $(CYGPATH_W) 'WindTrans.c'; else $(CYGPATH_W) '$(srcdir)/WindTrans.c'; fi`
+
 cdo-Writegrid.o: Writegrid.c
 @am__fastdepCC_TRUE@	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(cdo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cdo-Writegrid.o -MD -MP -MF $(DEPDIR)/cdo-Writegrid.Tpo -c -o cdo-Writegrid.o `test -f 'Writegrid.c' || echo '$(srcdir)/'`Writegrid.c
 @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/cdo-Writegrid.Tpo $(DEPDIR)/cdo-Writegrid.Po
diff --git a/src/Math.c b/src/Math.c
index a6db764..3a7404d 100644
--- a/src/Math.c
+++ b/src/Math.c
@@ -71,6 +71,8 @@ void *Math(void *argument)
   int operatorID = cdoOperatorID();
   int operfunc = cdoOperatorF1(operatorID);
 
+  if ( operfunc == FNINT ) cdo_check_round();
+
   double rc = 0;
   if ( operfunc == POW )
     {
@@ -127,7 +129,7 @@ void *Math(void *argument)
                   break;
                 case FNINT:
                   for ( i = 0; i < gridsize; i++ )
-                    array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : (double)lround(array1[i]);
+                    array2[i] = DBL_IS_EQUAL(array1[i], missval1) ? missval1 : round(array1[i]);
                   break;
                 case SQR:
                   for ( i = 0; i < gridsize; i++ )
diff --git a/src/Pressure.c b/src/Pressure.c
index 39a6193..18f65a0 100644
--- a/src/Pressure.c
+++ b/src/Pressure.c
@@ -36,8 +36,7 @@
 void *Pressure(void *argument)
 {
   int mode;
-  enum {ECHAM_MODE, WMO_MODE};
-  int ps_code = 0, lsp_code = 0;
+  gribcode_t gribcodes = {0};
   int nrecs;
   int i, k, offset;
   int varID, levelID;
@@ -49,7 +48,6 @@ void *Pressure(void *argument)
   char paramstr[32];
   char varname[CDI_MAX_NAME];
   double minval, maxval;
-  double *ps_prog = NULL, *full_press = NULL, *half_press = NULL, *deltap = NULL;
   double *pout = NULL;
 
   cdoInitialize(argument);
@@ -69,20 +67,24 @@ void *Pressure(void *argument)
   int nhlev;
   double *vct = vlist_read_vct(vlistID1, &zaxisIDh, &nvct, &nhlev, &nhlevf, &nhlevh);
 
-  if ( zaxisIDh != -1 && gridsize > 0 )
-    {
-      ps_prog    = (double*) Malloc(gridsize*sizeof(double));
-      deltap     = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-      full_press = (double*) Malloc(gridsize*nhlevf*sizeof(double));
-      half_press = (double*) Malloc(gridsize*nhlevh*sizeof(double));
-    }
-  else
-    cdoAbort("No 3D variable with hybrid sigma pressure coordinate found!");
+  bool l3Dvars = (zaxisIDh != -1 && gridsize > 0);
+  if ( !l3Dvars ) cdoAbort("No 3D variable with hybrid sigma pressure coordinate found!");
+    
+  double *ps_prog    = (double*) Malloc(gridsize*sizeof(double));
+  double *deltap     = (double*) Malloc(gridsize*nhlevf*sizeof(double));
+  double *full_press = (double*) Malloc(gridsize*nhlevf*sizeof(double));
+  double *half_press = (double*) Malloc(gridsize*nhlevh*sizeof(double));
 
   if ( operatorID == PRESSURE_FL || operatorID == DELTAP )
-    zaxisIDp = zaxisCreate(ZAXIS_HYBRID, nhlevf);
+    {
+      if ( cdoVerbose ) cdoPrint("Creating ZAXIS_HYBRID .. (nhlevf=%d)", nhlevf);
+      zaxisIDp = zaxisCreate(ZAXIS_HYBRID, nhlevf);
+    }
   else
-    zaxisIDp = zaxisCreate(ZAXIS_HYBRID_HALF, nhlevh);
+    {
+      if ( cdoVerbose ) cdoPrint("Creating ZAXIS_HYBRID_HALF .. (nhlevh=%d)", nhlevh);
+      zaxisIDp = zaxisCreate(ZAXIS_HYBRID_HALF, nhlevh);
+    }
 
   double *level = (double*) Malloc(nhlevh*sizeof(double));
   for ( int l = 0; l < nhlevh; l++ ) level[l] = l+1;
@@ -123,13 +125,20 @@ void *Pressure(void *argument)
 	  if ( tableNum == 2 )
 	    {
 	      mode = WMO_MODE;
-	      ps_code    =   1;
+	      wmo_gribcodes(&gribcodes);
 	    }
 	  else if ( tableNum == 128 )
 	    {
 	      mode = ECHAM_MODE;
-	      ps_code    = 134;
-	      lsp_code   = 152;
+	      echam_gribcodes(&gribcodes);
+	    }
+          //  KNMI: HIRLAM model version 7.2 uses tableNum=1    (LAMH_D11*)
+          //  KNMI: HARMONIE model version 36 uses tableNum=1   (grib*)   (opreational NWP version)
+          //  KNMI: HARMONIE model version 38 uses tableNum=253 (grib,grib_md) and tableNum=1 (grib_sfx) (research version)
+	  else if ( tableNum == 1 || tableNum == 253 )
+	    {
+	      mode = HIRLAM_MODE;
+	      hirlam_harmonie_gribcodes(&gribcodes);
 	    }
 	  else
 	    mode = -1;
@@ -137,12 +146,15 @@ void *Pressure(void *argument)
       else
 	{
 	  mode = ECHAM_MODE;
-	  ps_code    = 134;
-	  lsp_code   = 152;
+	  echam_gribcodes(&gribcodes);
 	}
 
       if ( cdoVerbose )
-	cdoPrint("Mode = %d  Center = %d  Param = %s", mode, instNum, paramstr);
+        {
+	  vlistInqVarName(vlistID1, varID, varname);
+	  cdoPrint("Mode = %d  Center = %d TableNum =%d Code = %d Param = %s Varname = %s varID = %d",
+                   mode, instNum,tableNum,  code, paramstr, varname, varID);
+        }
 
       if ( code <= 0 )
 	{
@@ -161,14 +173,17 @@ void *Pressure(void *argument)
 
       if ( mode == ECHAM_MODE )
 	{
-	  if      ( code == ps_code    && nlevel == 1     ) psID    = varID;
-	  else if ( code == lsp_code   && nlevel == 1     ) lnpsID  = varID;
-	  /* else if ( code == 156 ) gheightID = varID; */
+	  if      ( code == gribcodes.ps   && nlevel == 1 ) psID    = varID;
+	  else if ( code == gribcodes.lsp  && nlevel == 1 ) lnpsID  = varID;
 	}
       else if ( mode == WMO_MODE )
 	{
-	  if ( code == ps_code    && nlevel == 1     ) psID    = varID;
+	  if ( code == gribcodes.ps        && nlevel == 1 ) psID    = varID;
 	}
+      else if ( mode == HIRLAM_MODE )
+	{
+	  if ( code == gribcodes.ps        && nlevel == 1 ) psID    = varID;
+        }
     }
 
   int pvarID = lnpsID;
diff --git a/src/Remap.c b/src/Remap.c
index edf1aa3..8a1f6c2 100644
--- a/src/Remap.c
+++ b/src/Remap.c
@@ -106,57 +106,12 @@ int maptype2operfunc(int map_type, int submap_type, int num_neighbors, int remap
 {
   int operfunc = -1;
 
-  if ( map_type == MAP_TYPE_CONSERV )
-    {
-      if ( remap_order == 2 )
-	{
-	  operfunc = REMAPCON2;
-	  // cdoPrint("Using remapcon2");
-	}
-      else
-	{
-	  operfunc = REMAPCON;
-	  // cdoPrint("Using remapcon");
-	}
-    }
-  else if ( map_type == MAP_TYPE_CONSERV_YAC )
-    {
-      if ( submap_type == SUBMAP_TYPE_LAF )
-	{
-	  operfunc = REMAPLAF;
-	  // cdoPrint("Using remaplaf");
-	}
-      else
-	{
-	  operfunc = REMAPYCON;
-	  // cdoPrint("Using remapycon");
-	}
-    }
-  else if ( map_type == MAP_TYPE_BILINEAR )
-    {
-      operfunc = REMAPBIL;
-      // cdoPrint("Using remapbil");
-    }
-  else if ( map_type == MAP_TYPE_BICUBIC )
-    {
-      operfunc = REMAPBIC;
-      // cdoPrint("Using remapbic");
-    }
-  else if ( map_type == MAP_TYPE_DISTWGT )
-    {
-      if ( num_neighbors == 1 )
-	{
-	  operfunc = REMAPNN;
-	  // cdoPrint("Using remapnn");
-	}
-      else
-	{
-	  operfunc = REMAPDIS;
-	  // cdoPrint("Using remapdis");
-	}
-    }
-  else
-    cdoAbort("Unsupported mapping method (map_type = %d)", map_type);
+  if      ( map_type == MAP_TYPE_CONSERV )     operfunc = (remap_order == 2) ? REMAPCON2 : REMAPCON;
+  else if ( map_type == MAP_TYPE_CONSERV_YAC ) operfunc = (submap_type == SUBMAP_TYPE_LAF) ? REMAPLAF : REMAPYCON;
+  else if ( map_type == MAP_TYPE_BILINEAR )    operfunc = REMAPBIL;
+  else if ( map_type == MAP_TYPE_BICUBIC )     operfunc = REMAPBIC;
+  else if ( map_type == MAP_TYPE_DISTWGT )     operfunc = (num_neighbors == 1) ? REMAPNN : REMAPDIS;
+  else  cdoAbort("Unsupported mapping method (map_type = %d)", map_type);
 
   return operfunc;
 } 
@@ -164,8 +119,7 @@ int maptype2operfunc(int map_type, int submap_type, int num_neighbors, int remap
 static
 void print_remap_info(int operfunc, int remap_genweights, remapgrid_t *src_grid, remapgrid_t *tgt_grid, int nmiss)
 {
-  char line[256];
-  char tmpstr[256];
+  char line[256], tmpstr[256];
 
   line[0] = 0;
 
@@ -323,10 +277,7 @@ void get_remap_env(void)
     }
 
 #if defined(_OPENMP)
-  if ( ompNumThreads == 1 )
-    sort_mode = HEAP_SORT;
-  else
-    sort_mode = MERGE_SORT;
+  sort_mode = (ompNumThreads == 1) ? HEAP_SORT : MERGE_SORT;
 #endif
 
   envstr = getenv("REMAP_SORT_MODE");
@@ -513,7 +464,6 @@ bool is_global_grid(int gridID)
        (projtype == CDI_PROJ_SINU) ||
        (projtype == CDI_PROJ_LCC)  ||
        (gridtype == GRID_LONLAT && non_global) ||
-       (gridtype == GRID_LCC) ||
        (gridtype == GRID_CURVILINEAR && non_global) ) global_grid = false;
 
   return global_grid;
@@ -556,7 +506,6 @@ int set_remapgrids(int filetype, int vlistID, int ngrids, bool *remapgrids)
            projtype != CDI_PROJ_SINU    &&
            projtype != CDI_PROJ_LCC     &&
 	   gridtype != GRID_GAUSSIAN    &&
-	   gridtype != GRID_LCC         &&
 	   gridtype != GRID_GME         &&
 	   gridtype != GRID_CURVILINEAR &&
 	   gridtype != GRID_UNSTRUCTURED )
@@ -720,27 +669,44 @@ static
 void links_per_value(remapvars_t *remapvars)
 {
   long num_links = remapvars->num_links;
-  const int *restrict dst_add = remapvars->tgt_cell_add;
+  int lpv = -1;
 
-  int lpv = 1;
-  int ival = dst_add[0];
-  for ( long n = 1; n < num_links; ++n )
-    if ( dst_add[n] == ival ) lpv++;
-    else break;
-
-  if ( num_links%lpv != 0 ) lpv = -1;
-  else if ( lpv > 1 )
+  if ( num_links > 0 )
     {
-      for ( long n = 1; n < num_links/lpv; ++n )
+      lpv = 1;
+      const int *restrict dst_add = remapvars->tgt_cell_add;
+      int ival = dst_add[0];
+      for ( long n = 1; n < num_links; ++n )
+        if ( dst_add[n] == ival ) lpv++;
+        else break;
+
+      if ( num_links%lpv != 0 ) lpv = -1;
+      else if ( lpv == 1 )
+        {
+          for ( long n = 1; n < num_links; ++n )
+            {
+              if ( dst_add[n] == dst_add[n-1] )
+                {
+                  lpv = -1;
+                  break;
+                }
+            }
+        }
+      else if ( lpv > 1 )
         {
-          ival = dst_add[n*lpv];
-          for ( int k = 1; k < lpv; ++k )
-            if ( dst_add[n*lpv+k] != ival )
-              {
-                lpv = -1;
-                break;
-              }
-          if ( lpv == -1 ) break;
+          for ( long n = 1; n < num_links/lpv; ++n )
+            {
+              ival = dst_add[n*lpv];
+              for ( int k = 1; k < lpv; ++k )
+                {
+                  if ( dst_add[n*lpv+k] != ival )
+                    {
+                      lpv = -1;
+                      break;
+                    }
+                }
+              if ( lpv == -1 ) break;
+            }
         }
     }
 
@@ -788,7 +754,6 @@ void *Remap(void *argument)
   int need_gradiants = FALSE;
   char varname[CDI_MAX_NAME];
   double missval;
-  double *grad1_lat = NULL, *grad1_lon = NULL, *grad1_latlon = NULL;
   remap_t *remaps = NULL;
   char *remap_file = NULL;
 
@@ -936,13 +901,12 @@ void *Remap(void *argument)
       gridsize2 = gridInqSize(gridID2);
       if ( gridInqType(gridID2) == GRID_GME )
 	{
-	  int gridID2_gme;
-	  int isize = 0;
 	  remaps[0].tgt_grid.nvgp = gridInqSize(gridID2);
 	  remaps[0].tgt_grid.vgpm = (int*) Realloc(remaps[0].tgt_grid.vgpm, gridInqSize(gridID2)*sizeof(int));
-	  gridID2_gme = gridToUnstructured(gridID2, 1);
+	  int gridID2_gme = gridToUnstructured(gridID2, 1);
 	  gridInqMaskGME(gridID2_gme, remaps[0].tgt_grid.vgpm);
-	  for ( i = 0; i < gridsize2; ++i )
+	  int isize = 0;
+	  for ( int i = 0; i < gridsize2; ++i )
 	    if ( remaps[0].tgt_grid.vgpm[i] ) isize++;
 	  gridsize2 = isize;
 	}
@@ -981,12 +945,9 @@ void *Remap(void *argument)
   else
     remap_order = 1;
 
-  if ( need_gradiants )
-    {
-      grad1_lat    = (double*) Malloc(grid1sizemax*sizeof(double));
-      grad1_lon    = (double*) Malloc(grid1sizemax*sizeof(double));
-      grad1_latlon = (double*) Malloc(grid1sizemax*sizeof(double));
-    }
+  double *grad1_lat    = need_gradiants ? (double*) Malloc(grid1sizemax*sizeof(double)) : NULL;
+  double *grad1_lon    = need_gradiants ? (double*) Malloc(grid1sizemax*sizeof(double)) : NULL;
+  double *grad1_latlon = need_gradiants ? (double*) Malloc(grid1sizemax*sizeof(double)) : NULL;
 
   double *array1 = (double*) Malloc(grid1sizemax*sizeof(double));
   int *imask = (int*) Malloc(grid1sizemax*sizeof(int));
@@ -1064,10 +1025,7 @@ void *Remap(void *argument)
 	    }
 
 	  for ( i = 0; i < gridsize; i++ )
-	    if ( DBL_IS_EQUAL(array1[i], missval) )
-	      imask[i] = FALSE;
-	    else
-	      imask[i] = TRUE;
+            imask[i] = DBL_IS_EQUAL(array1[i], missval) ? FALSE : TRUE;
 
 	  for ( r = nremaps-1; r >= 0; r-- )
 	    {
@@ -1092,12 +1050,6 @@ void *Remap(void *argument)
 		}
 	      else
 		{
-                  /*
-		  r = nremaps - 1;
-                  remapVarsFree(&remaps[r].vars);
-                  remapGridFree(&remaps[r].src_grid);
-                  remapGridFree(&remaps[r].tgt_grid);
-                  */
                   int n0 = 0;
                   if ( max_remaps > 1 && remaps[0].nused > remaps[1].nused ) n0 = 1;
                   remapVarsFree(&remaps[n0].vars);
diff --git a/src/Rotuv.c b/src/Rotuv.c
index 672b8b4..4cb0923 100644
--- a/src/Rotuv.c
+++ b/src/Rotuv.c
@@ -63,11 +63,7 @@ void rot_uv_back(int gridID, double *us, double *vs)
         double yval = phirot_to_phi(yvals[ilat], xvals[ilon], ypole, angle);
 
 	usvs_to_uv(us[i], vs[i], yval, xval, ypole, xpole, &u, &v);
-	/*
-	if ( i%100 == 0 )
-	fprintf(stderr, "%d %d %g %g %g %g %g %g %g %g\n",
-		ilat, ilon, us[i], vs[i], yvals[ilat], xvals[ilon], ypole, xpole, u, v);
-	*/
+
 	us[i] = u;
 	vs[i] = v;
       }
@@ -89,6 +85,7 @@ void *Rotuv(void *argument)
   int chcodes[MAXARG];
   char *chvars[MAXARG];
   char varname[CDI_MAX_NAME];
+  char varname2[CDI_MAX_NAME];
   double *single, *usvar = NULL, *vsvar = NULL;
 
   cdoInitialize(argument);
@@ -98,27 +95,25 @@ void *Rotuv(void *argument)
   int nch = operatorArgc();
   if ( nch%2 ) cdoAbort("Odd number of input arguments!");
 
-  bool lvar = false;
-  bool lcode = true;
+  bool lvar = false; // We have a list of codes
   int len = (int)strlen(operatorArgv()[0]);
-  for ( int i = 0; i < len; ++i )
+  int ix = (operatorArgv()[0][0] == '-') ? 1 : 0;
+  for ( int i = ix; i < len; ++i )
     if ( !isdigit(operatorArgv()[0][i]) )
       {
-        lcode = false;
+        lvar = true; // We have a list of variables
         break;
       }
 
-  if ( lcode )
+  if ( lvar )
     {
-      lvar = false;
       for ( int i = 0; i < nch; i++ )
-	chcodes[i] = parameter2int(operatorArgv()[i]);
+	chvars[i] = operatorArgv()[i];
     }
   else
     {
-      lvar = true;
       for ( int i = 0; i < nch; i++ )
-	chvars[i] = operatorArgv()[i];
+	chcodes[i] = parameter2int(operatorArgv()[i]);
     }
 
   int streamID1 = streamOpenRead(cdoStreamName(0));
@@ -248,10 +243,21 @@ void *Rotuv(void *argument)
 	  varID2 = varID;
 
 	  if ( cdoVerbose )
-	    cdoPrint("Using code %d [%d](u) and code %d [%d](v)",
-		     vlistInqVarCode(vlistID1, varID1), chcodes[i],
-		     vlistInqVarCode(vlistID1, varID2), chcodes[i+1]);
-	  
+            {
+              if ( lvar )
+                {
+                  vlistInqVarName(vlistID2, varID1, varname);
+                  vlistInqVarName(vlistID2, varID2, varname2);
+                  cdoPrint("Using var %s [%s](u) and var %s [%s](v)",
+                           varname, chvars[i],
+                           varname2, chvars[i+1]);
+                }
+              else
+                cdoPrint("Using code %d [%d](u) and code %d [%d](v)",
+                         vlistInqVarCode(vlistID1, varID1), chcodes[i],
+                         vlistInqVarCode(vlistID1, varID2), chcodes[i+1]);
+            }
+
 	  gridID   = vlistInqVarGrid(vlistID1, varID);
 	  gridsize = gridInqSize(gridID);
 	  nlevel1  = zaxisInqSize(vlistInqVarZaxis(vlistID1, varID1));
diff --git a/src/Runstat.c b/src/Runstat.c
index 87222b5..1b791e7 100644
--- a/src/Runstat.c
+++ b/src/Runstat.c
@@ -30,7 +30,6 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
 
diff --git a/src/Samplegrid.c b/src/Samplegrid.c
new file mode 100644
index 0000000..64e6eb1
--- /dev/null
+++ b/src/Samplegrid.c
@@ -0,0 +1,240 @@
+/*
+   This module "SampleGrid" contains the following operators:
+
+    samplegrid      Resample current grid with given factor, typically 2 (which will half the resolution);
+                    tested on curvilinear and LCC grids;
+    subgrid         Similar to selindexbox but this operator works for LCC grids (tested on HARMONIE NWP model).
+*/
+
+#include <cdi.h>
+#include "cdo_int.h"
+#include "pstream.h"
+#include "grid.h"
+
+
+static
+void sampleData(double *array1, int gridID1, double *array2, int gridID2, int resampleFactor)
+{
+  long nlon1 = gridInqXsize(gridID1);
+  long nlat1 = gridInqYsize(gridID1);
+
+  long nlon2 = gridInqXsize(gridID2);
+  long nlat2 = gridInqYsize(gridID2);
+
+  if ( cdoDebugExt >= 100 )
+    cdoPrint("%s(): (nlon1: %d; nlat1: %d) => (nlon2: %d; nlat2: %d); gridID1: %d; gridID2: %d; resampleFactor: %d)",
+             __func__, nlon1, nlat1, nlon2,nlat2, gridID1, gridID2, resampleFactor);
+
+  for ( long ilat1 = 0; ilat1 < nlat1; ilat1+=resampleFactor )
+    for ( long ilon1 = 0; ilon1 < nlon1; ilon1+=resampleFactor )
+      *array2++ = array1[ilat1*nlon1 + ilon1];
+}
+
+static
+void cropData(double *array1, int gridID1, double *array2, int gridID2, int subI0, int subI1, int  subJ0, int  subJ1 )
+{
+  long nlon1 = gridInqXsize(gridID1);
+  long nlon2 = gridInqXsize(gridID2);
+  long rowLen = subI1 - subI0 + 1; // must be same as nlon1
+
+  if ( rowLen!= nlon2 )
+    cdoAbort("cropData() rowLen!= nlon2 [%d != %d]", rowLen, nlon2);
+
+  if ( cdoDebugExt>=10 ) cdoPrint("cropData(%d,%d,%d,%d) ...", subI0, subI1, subJ0, subJ1 );
+
+  long array2Idx = 0;
+  for ( long ilat1 = subJ0; ilat1 <= subJ1; ilat1++ ) // copy the last row as well..
+    {
+      memcpy((void*)&array2[array2Idx], (void*)&array1[ilat1*nlon1 + subI0], rowLen*sizeof(double));
+      array2Idx += rowLen;
+    }
+}
+
+
+void *Samplegrid(void *argument)
+{
+  int nrecs;
+  int varID, levelID;
+  int resampleFactor;
+  int subI0 = 0, subI1 = 0, subJ0 = 0, subJ1 = 0;
+  int index;
+  int nmiss;
+  typedef struct {
+    int gridSrcID, gridIDsampled;
+    int *cellidx, nvals;
+    int subI0, subI1, subJ0, subJ1;
+  } sbox_t;
+
+  cdoInitialize(argument);
+
+  int SAMPLEGRID = cdoOperatorAdd("samplegrid",  0, 0, "resample factor, typically 2 (which will half the resolution)");
+  int SUBGRID    = cdoOperatorAdd("subgrid",  0, 0, " sub-grid indices: i0,i1,j0,j1");
+
+  int operatorID = cdoOperatorID();
+
+  int nch = operatorArgc();
+
+  if ( operatorID == SAMPLEGRID )
+    {
+      if ( cdoDebugExt ) cdoPrint("samplegrid operator requested..");
+      if ( nch < 1 ) cdoAbort("Number of input arguments < 1; At least 1 argument needed: resample-factor (2,3,4, .. etc)");
+      resampleFactor = parameter2int(operatorArgv()[0]);
+
+      if ( cdoDebugExt ) cdoPrint("resampleFactor = %d", resampleFactor);
+    }
+  else if ( operatorID == SUBGRID )
+    {
+      if ( cdoDebugExt ) cdoPrint("subgrid operator requested..");
+      if ( nch < 4 ) cdoAbort("Number of input arguments < 4; Must specify sub-grid indices: i0,i1,j0,j1; This works only with LCC grid. For other grids use: selindexbox");
+      subI0 = parameter2int(operatorArgv()[0]);
+      subI1 = parameter2int(operatorArgv()[1]);
+      subJ0 = parameter2int(operatorArgv()[2]);
+      subJ1 = parameter2int(operatorArgv()[3]);
+    }
+  else
+    cdoAbort("Unknown operator ...");
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
+
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  int nvars = vlistNvars(vlistID1);
+  bool *vars  = (bool *) Malloc(nvars*sizeof(bool));
+  for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
+
+  int ngrids = vlistNgrids(vlistID1);
+
+  if ( cdoDebugExt ) cdoPrint("ngrids = %d", ngrids);
+
+  sbox_t *sbox = (sbox_t *) Malloc(ngrids*sizeof(sbox_t));
+
+  for ( int index = 0; index < ngrids; index++ )
+    {
+      int gridSrcID = vlistGrid(vlistID1, index);
+      int gridIDsampled = -1;
+
+      if ( gridInqSize(gridSrcID ) <= 1 ) continue;
+
+      int gridtype = gridInqType(gridSrcID);
+      if ( ! (gridtype == GRID_GAUSSIAN || gridtype == GRID_LONLAT || gridtype == GRID_PROJECTION ||
+              gridtype == GRID_CURVILINEAR || gridtype == GRID_GENERIC) )
+        cdoAbort("Unsupported gridtype: %s", gridNamePtr(gridtype));
+
+      if ( operatorID == SAMPLEGRID )
+        {
+          gridIDsampled = cdo_define_sample_grid(gridSrcID, resampleFactor);
+        }
+      else if ( operatorID == SUBGRID )
+        {
+          gridIDsampled = cdo_define_subgrid_grid(gridSrcID, subI0, subI1, subJ0, subJ1);
+        }
+
+      sbox[index].gridSrcID = gridSrcID;
+      sbox[index].gridIDsampled = gridIDsampled;
+
+      // if ( cdoDebugExt>=10 ) cdo_print_grid(gridSrcID, 1);
+      // if ( cdoDebugExt>=10 ) cdo_print_grid(gridIDsampled, 1);
+      
+      vlistChangeGridIndex(vlistID2, index, gridIDsampled);
+
+      for ( varID = 0; varID < nvars; varID++ )
+        if ( gridSrcID == vlistInqVarGrid(vlistID1, varID) )
+          vars[varID] = true;
+    }
+
+  if ( cdoDebugExt )
+    {
+      if ( operatorID == SAMPLEGRID ) cdoPrint("Resampled grid has been created.");
+      if ( operatorID == SUBGRID    ) cdoPrint("Sub-grid has been created.");
+    }
+
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+  streamDefVlist(streamID2, vlistID2);
+
+  int gridsize = vlistGridsizeMax(vlistID1);
+  if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
+  double *array1 = (double *) Malloc(gridsize*sizeof(double));
+
+  int gridsize2 = vlistGridsizeMax(vlistID2);
+  if ( vlistNumber(vlistID2) != CDI_REAL ) gridsize2 *= 2;
+  double *array2 = (double *) Malloc(gridsize2*sizeof(double));
+
+  if ( cdoDebugExt ) cdoPrint("gridsize = %ld, gridsize2 = %ld", gridsize, gridsize2);
+
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+
+      streamDefTimestep(streamID2, tsID);
+
+      for ( int recID = 0; recID < nrecs; recID++ )
+        {
+          streamInqRecord(streamID1, &varID, &levelID);
+          streamReadRecord(streamID1, array1, &nmiss);
+
+          streamDefRecord(streamID2, varID, levelID);
+
+          if ( cdoDebugExt>=20 ) cdoPrint("Processing record (%d) of %d.",recID, nrecs);
+
+          if ( vars[varID] )
+            {
+              int gridSrcID = vlistInqVarGrid(vlistID1, varID);
+
+              for ( index = 0; index < ngrids; index++ )
+                if ( gridSrcID == sbox[index].gridSrcID ) break;
+
+              if ( index == ngrids ) cdoAbort("Internal problem, grid not found!");
+
+              int gridIDsampled = sbox[index].gridIDsampled;
+              gridsize2 = gridInqSize(gridIDsampled);
+
+              if (operatorID == SAMPLEGRID)
+                {
+                  sampleData(array1, gridSrcID, array2, gridIDsampled, resampleFactor);
+                }
+              else if (operatorID == SUBGRID)
+                {
+                  cropData(array1, gridSrcID, array2, gridIDsampled, subI0, subI1, subJ0, subJ1);
+                }
+
+              if ( nmiss )
+                {
+                  nmiss = 0;
+                  double missval = vlistInqVarMissval(vlistID2, varID);
+                  for ( int i = 0; i < gridsize2; i++ )
+                    if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
+                }
+
+              streamWriteRecord(streamID2, array2, nmiss);
+            }
+          else
+            {
+              streamWriteRecord(streamID2, array1, nmiss);
+            }
+        }
+
+      tsID++;
+    }
+
+  streamClose(streamID2);
+  streamClose(streamID1);
+
+  vlistDestroy(vlistID2);
+
+  if ( vars ) Free(vars);
+  if ( array2 ) Free(array2);
+  if ( array1 ) Free(array1);
+
+  if ( sbox ) Free(sbox);
+
+  cdoFinish();
+
+  return 0;
+}
diff --git a/src/Selbox.c b/src/Selbox.c
index 7d23c44..4e4eddd 100644
--- a/src/Selbox.c
+++ b/src/Selbox.c
@@ -135,6 +135,8 @@ int gengrid(int gridID1, int lat1, int lat2, int lon11, int lon12, int lon21, in
   int nlon2 = nlon21 + nlon22;
   int nlat2 = lat2 - lat1 + 1;
 
+  if ( cdoVerbose ) cdoPrint("nlon=%d nlat=%d", nlon2, nlat2);
+
   int gridtype = gridInqType(gridID1);
 
   int gridID2 = gridCreate(gridtype, nlon2*nlat2);
@@ -669,9 +671,6 @@ int gencellgrid(int gridID1, int *gridsize2, int **cellidx)
 
 void genindexbox(int argc_offset, int gridID1, int *lat1, int *lat2, int *lon11, int *lon12, int *lon21, int *lon22)
 {
-  int nlon, nlat;
-  int temp;
-
   operatorCheckArgc(argc_offset+4);
 
   *lon11 = parameter2int(operatorArgv()[argc_offset+0]);
@@ -681,20 +680,20 @@ void genindexbox(int argc_offset, int gridID1, int *lat1, int *lat2, int *lon11,
 
   if ( *lat1 > *lat2 )
     {
-      temp = *lat1;
+      int temp = *lat1;
       *lat1 = *lat2;
       *lat2 = temp;
     }
 
-  nlon = gridInqXsize(gridID1);
-  nlat = gridInqYsize(gridID1);
+  int nlon = gridInqXsize(gridID1);
+  int nlat = gridInqYsize(gridID1);
 
   if ( *lat1 < 1 )
     {
       cdoWarning("First latitude index out of range, set to 1!");
       *lat1 = 1;
     }
-  if ( *lat2 > nlat )
+  if ( *lat1 > nlat )
     {
       cdoWarning("First latitude index out of range, set to %d!", nlat);
       *lat1 = nlat;
@@ -714,6 +713,16 @@ void genindexbox(int argc_offset, int gridID1, int *lat1, int *lat2, int *lon11,
       cdoWarning("First longitude index out of range, set to 1!");
       *lon11 = 1;
     }
+  if ( *lon11 > nlon )
+    {
+      cdoWarning("First longitude index out of range, set to %d!", nlon);
+      *lon11 = nlon;
+    }
+  if ( *lon12 < 1 )
+    {
+      cdoWarning("Last longitude index out of range, set to 1!");
+      *lon12 = 1;
+    }
   if ( *lon12 > nlon+1 )
     {
       cdoWarning("Last longitude index out of range, set to %d!", nlon);
@@ -753,7 +762,11 @@ int genindexgrid(int gridID1, int *lat1, int *lat2, int *lon11, int *lon12, int
 {
   genindexbox(0, gridID1, lat1, lat2, lon11, lon12, lon21, lon22);
 
-  int gridID2 = gengrid(gridID1, *lat1, *lat2, *lon11, *lon12, *lon21, *lon22);
+  int gridID2 = -1;
+  if ( gridInqType(gridID1) == GRID_PROJECTION && gridInqProjType(gridID1) == CDI_PROJ_LCC )
+    gridID2 = cdo_define_subgrid_grid(gridID1, *lon11, *lon12, *lat1, *lat2);
+  else
+    gridID2 = gengrid(gridID1, *lat1, *lat2, *lon11, *lon12, *lon21, *lon22);
 
   return gridID2;
 }
@@ -858,6 +871,7 @@ void *Selbox(void *argument)
 
       if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN || gridtype == GRID_CURVILINEAR ||
            (gridtype == GRID_PROJECTION && gridInqProjType(gridID1) == CDI_PROJ_RLL) ||
+           (gridtype == GRID_PROJECTION && gridInqProjType(gridID1) == CDI_PROJ_LCC) ||
 	   (operatorID == SELINDEXBOX && gridtype == GRID_GENERIC && 
 	    gridInqXsize(gridID1) > 0 && gridInqYsize(gridID1) > 0) ||
 	   (operatorID == SELLONLATBOX && gridtype == GRID_UNSTRUCTURED) )
diff --git a/src/Select.c b/src/Select.c
index 4d0bc65..75fb560 100644
--- a/src/Select.c
+++ b/src/Select.c
@@ -22,17 +22,15 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include "error.h"
-#include "util.h"
-#include "pmlist.h"
 #include "sellist.h"
 
 
 double datestr_to_double(const char *datestr, int opt);
 
+bool *cdo_read_timestepmask(const char *maskfile, int *n);
+
 static
 void write_const_vars(int streamID2, int vlistID2, int nvars, double **vardata2)
 {
@@ -58,7 +56,39 @@ void write_const_vars(int streamID2, int vlistID2, int nvars, double **vardata2)
           vardata2[varID2c] = NULL;
         }
     }
-}  
+}
+
+static
+void eval_timestepmask(const char *maskfile, list_t *kvlist)
+{
+  int n = 0;
+  bool *imask = cdo_read_timestepmask(maskfile, &n);
+
+  int nvals = 0;
+  for ( int i = 0; i < n; ++i ) if ( imask[i] ) nvals++;
+  if ( nvals == 0 ) cdoPrint("timestepmask has no values!");
+  else
+    {
+      char **values = (char**) Malloc(nvals*sizeof(char*));
+      int j = 0;
+      for ( int i = 0; i < n; ++i )
+        {
+          if ( imask[i] )
+            {
+              size_t length = (size_t)log10(j+1)+2;
+              values[j] = (char*) Malloc(length*sizeof(char));
+              sprintf(values[j++], "%d", i+1);
+            }
+        }
+
+      kvlist_append(kvlist, "timestep", (const char **)values, nvals);
+
+      for ( int i = 0; i < nvals; ++i ) Free(values[i]);
+      Free(values);
+    }
+      
+  Free(imask);
+}
 
 
 void *Select(void *argument)
@@ -104,6 +134,13 @@ void *Select(void *argument)
   if ( kvlist_parse_cmdline(kvlist, nsel, argnames) != 0 ) cdoAbort("Parse error!");
   if ( cdoVerbose ) kvlist_print(kvlist);
 
+  keyValues_t *kv = kvlist_search(kvlist, "timestepmask");
+  if ( kv && kv->nvalues > 0 )
+    {
+      if ( kvlist_search(kvlist, "timestep") ) cdoAbort("Parameter timestep and timestepmask can't be combined!");
+      eval_timestepmask(kv->values[0], kvlist);
+    }
+
   sellist_t *sellist = sellist_create(kvlist);
 
   SELLIST_ADD_INT(timestep_of_year, "Timestep of year");
@@ -128,11 +165,15 @@ void *Select(void *argument)
   SELLIST_ADD_WORD(enddate,         "End date");
   SELLIST_ADD_WORD(season,          "Season");
   SELLIST_ADD_WORD(date,            "Date");
+  SELLIST_ADD_WORD(timestepmask,    "Timestep mask");
 
   if ( cdoVerbose ) sellist_print(sellist);
 
   sellist_verify(sellist);
 
+  if ( SELLIST_NVAL(timestepmask) > 1 ) cdoAbort("Key timestepmask has too many values!");
+  UNUSED(timestepmask);
+
   int streamCnt = cdoStreamCnt();
   int nfiles = streamCnt - 1;
 
diff --git a/src/Selindex.c b/src/Selgridcell.c
similarity index 84%
rename from src/Selindex.c
rename to src/Selgridcell.c
index d81404a..94ff1f1 100644
--- a/src/Selindex.c
+++ b/src/Selgridcell.c
@@ -62,7 +62,7 @@ void sel_index(double *array1, double *array2, int nind, int *indarr)
 }
 
 
-void *Selindex(void *argument)
+void *Selgridcell(void *argument)
 {
   int nrecs;
   int varID, levelID;
@@ -77,10 +77,15 @@ void *Selindex(void *argument)
 
   cdoInitialize(argument);
 
-  cdoOperatorAdd("selindex", 0, 0, "grid cell indices (1-N)");
+  int SELGRIDCELL = cdoOperatorAdd("selgridcell", 0, 0, "grid cell indices (1-N)");
+  int DELGRIDCELL = cdoOperatorAdd("delgridcell", 0, 0, "grid cell indices (1-N)");
+
+  UNUSED(SELGRIDCELL);
 
   operatorInputArg(cdoOperatorEnter(0));
 
+  int operatorID = cdoOperatorID();
+
   int nind = args2int_lista(operatorArgc(), operatorArgv(), ilista);
   int *indarr = (int*) lista_dataptr(ilista);
 
@@ -111,12 +116,27 @@ void *Selindex(void *argument)
   vlistDefTaxis(vlistID2, taxisID2);
 
   int nvars = vlistNvars(vlistID1);
-  bool *vars  = (bool*) Malloc(nvars*sizeof(bool));
+  bool *vars = (bool*) Malloc(nvars*sizeof(bool));
   for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
 
   int ngrids = vlistNgrids(vlistID1);
   sindex_t *sindex = (sindex_t *) Malloc(ngrids*sizeof(sindex_t));
 
+  int ncells = nind;
+  int *cellidx = indarr;
+  if ( operatorID == DELGRIDCELL )
+    {
+      int gridsize = vlistGridsizeMax(vlistID1);
+      ncells = gridsize - nind;
+      cellidx = (int*) Malloc(gridsize*sizeof(int));
+      for ( int i = 0; i < gridsize; ++i ) cellidx[i] = 1;
+      for ( int i = 0; i < nind; ++i ) cellidx[indarr[i]] = 0;
+      int j = 0;
+      for ( int i = 0; i < gridsize; ++i )
+        if ( cellidx[i] == 1 ) cellidx[j++] = i;
+      if ( j != ncells ) cdoAbort("Internal error; number of cells differ");
+    }
+
   for ( index = 0; index < ngrids; index++ )
     {
       gridID1  = vlistGrid(vlistID1, index);
@@ -130,7 +150,7 @@ void *Selindex(void *argument)
           continue;
         }
 
-      gridID2 = genindexgrid(gridID1, nind, indarr);
+      gridID2 = genindexgrid(gridID1, ncells, cellidx);
 
       if ( gridID2 == -1 )
         {
@@ -191,7 +211,7 @@ void *Selindex(void *argument)
 
 	      gridsize2 = gridInqSize(sindex[index].gridID2);
 
-              sel_index(array1, array2, nind, indarr); 
+              sel_index(array1, array2, ncells, cellidx);
 
 	      if ( nmiss )
 		{
@@ -223,6 +243,8 @@ void *Selindex(void *argument)
 
   lista_destroy(ilista);
 
+  if ( operatorID == DELGRIDCELL ) Free(cellidx);
+
   cdoFinish();
 
   return 0;
diff --git a/src/Selmulti.c b/src/Selmulti.c
new file mode 100644
index 0000000..8695419
--- /dev/null
+++ b/src/Selmulti.c
@@ -0,0 +1,1180 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2012 Uwe Schulzweida, Uwe.Schulzweida at zmaw.de
+  See COPYING file for copying and redistribution conditions.
+
+  This program 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; version 2 of the License.
+
+  This program 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.
+*/
+
+#include <cdi.h>
+#include "cdo_int.h"
+#include "pstream.h"
+#include "listarray.h"
+
+// NOTE: All operators in this module works only on GRIB edition 1 files!
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void streamGrbChangeParameterIdentification(int code, int ltype, int lev);
+#if defined (__cplusplus)
+}
+#endif
+
+/*
+Supported notations:
+======================
+Selection provided on commandline:
+---------------------------------
+cdo selmulti,'(33/34;105;10)'
+ - or -
+cdo selmulti,'(33/34;105;10);(11/6;109;55)'
+cdo selmulti,'(33/34;105;10);(11/6;109;40/55)'
+cdo selmulti,'(*;105;10);(11/6;109;40/55);(*;105;2)'
+cdo selmulti,'{(33/34;105;10);(11/32,8;109;51/52/53/54/55)}'
+
+NOTE: ' .. ' are mandatory !
+
+Selection provided from a text file:
+---------------------------------
+
+cdo selmulti,selection_10m_wind.txt
+
+(*A*) Compact general notation, selection file content:
+
+(1; 103; 0)
+(33,34; 105; 10)
+(11,17; 105; 2)
+(71,73,74,75,61,62,65,117,67,122,121,11,131,66,84,111,112; 105; 0)
+# If nothing <'sel(' or 'del('>  is specified then
+# the operator -selmulti or -delmulti decides if it will be selection of extraction or delete
+# Explicite select or delete is also possible:
+#(11; 109; *)
+#(*; 105; *)
+#del(*; 109; *)
+#sel(*; 105; *)
+#sel(*; 100; *)
+
+# BUT simple array arithmetics should be also possible ("*" ~= mulc;  "+' ~= addc)
+sel(33,34;105,1000,3000):math(*2;)        # not implemented yet
+sel(11;105,500,1500,3000):math(+273.15;)  # not implemented yet
+
+(*B*) HIP.X notation (KNMI specific), selection file content:
+
+SELECT, PARAMETER=1, LEVTYPE=103, LEVEL=0
+SELECT, PARAMETER=33/34, LEVTYPE=105, LEVEL=10
+SELECT, PARAMETER=11/17, LEVTYPE=105, LEVEL=2
+SELECT, PARAMETER=71/73/74/75/61/62/65/117/67/122/121/11/131/66/84/111/112, LEVTYPE=105, LEVEL=0
+# Explicite delete is also possible:
+#DELETE, PARAMETER=128, LEVTYPE=109, LEVEL=*
+
+# BUT simple array arithmetics should be also possible (SCALE ~= mulc;  OFFSET ~= addc)
+
+# The following will convert Pressure from Pa into HPa; Temp from Kelvin to Celsius:
+SELECT, PARAMETER=1, LEVTYPE= 103, LEVEL=0, SCALE=0.01
+SELECT, PARAMETER=11, LEVTYPE=105, LEVEL=2, OFFSET=273.15
+SELECT, PARAMETER=33/34, LEVTYPE=105, LEVEL=10
+
+If SCALE and/or OFFSET are defined, then the data values are scaled as SCALE*(VALUE-OFFSET).
+The default value for SCALE is 1.0; the default for OFFSET is 0.0.
+
+**** changemulti ***********
+
+cdo changemulti,'{(134;1;*|1;105;*);{(6;1;*|6;105;*)};{(246;*;*|76;*;*)};{(247;*;*|58;*;*)};{(248;*;*|71;*;*)}' fileIN fileOUT
+
+
+cdo changemulti,'{(134;1;*|1;105;*)}' fileIN fileOUT
+# surface pressure has ECMWF code; change it into Hirlam notation ..
+grib_set -w indicatorOfParameter=134,indicatorOfTypeOfLevel=1 -s indicatorOfParameter=1,indicatorOfTypeOfLevel=105 ECMWF_H11_test0.grb ECMWF_H11_test1.grb
+
+cdo changemulti,'{(6;1;*|6;105;*)}' fileIN fileOUT
+# orography has wrong level-type, should be 105
+grib_set -w indicatorOfParameter=6,indicatorOfTypeOfLevel=1 -s indicatorOfParameter=6,indicatorOfTypeOfLevel=105 ECMWF_H11_test1.grb ECMWF_H11_test2.grb
+
+cdo changemulti,'{(246;*;*|76;*;*)}' fileIN fileOUT
+# change code for cloud_water
+grib_set -w indicatorOfParameter=246 -s indicatorOfParameter=76 ECMWF_H11_test2.grb ECMWF_H11_test3.grb
+
+cdo changemulti,'{(247;*;*|58;*;*)}' fileIN fileOUT
+# change code for cloud_ice
+grib_set -w indicatorOfParameter=247 -s indicatorOfParameter=58 ECMWF_H11_test3.grb ECMWF_H11_test4.grb
+
+cdo changemulti,'{(248;*;*|71;*;*)}' fileIN fileOUT
+# change code for total_cloud_cover
+grib_set -w indicatorOfParameter=248 -s indicatorOfParameter=71 ECMWF_H11_test4.grb ECMWF_H11_test.grb
+
+
+*/
+
+
+typedef struct {
+  lista_t *codeLST;
+  int  ncodes;
+
+  lista_t *levelTypeLST;
+  int  nlevelTypes;
+
+  lista_t *levelLST;
+  int  nlevels;
+  int  sel_or_del_or_change;  // sel_or_del_or_change:  0:  operator decides, 1:select , 2:delete, 3:change
+  int  simpleMath;  // 1:  simple array arithmetics ( *,+), 0: do nothing
+  float scale;
+  float offset;
+
+  int changedCode;     // used only changemulti mode
+  int changedLevelType;
+  int changedLevel;
+} TUPLEREC;
+
+
+
+int push_backIntList(int value, lista_t *list, int arraylen);
+int checkListContainsInt(int value, lista_t *list, int arraylen);
+int getIntFromList(int index, lista_t *list, int arraylen);
+
+#define MAX_TUPLES 1000
+static int NUMTUPLES = 0;
+static TUPLEREC *SelTUPLEREC[MAX_TUPLES];
+
+
+TUPLEREC *TUPLERECNew();
+void push_backSelTuple(TUPLEREC *tp);
+TUPLEREC * getSelTuple(int index);
+
+void printSelectionTuples();
+int getNumberOfSelectionTuples();
+int getNumberOfDeleteSelectionTuples();
+
+int multiSelectionParser(const char *filenameOrString);
+
+
+void *Selmulti(void *argument)
+{
+  int varID, levelID;
+  int nlevs, code, zaxisID;
+  int ltype = 0;
+  int varID2, levelID2;
+  int sellevel, selcode, selltype;
+  bool lcopy = false;
+  int nmiss;
+  int simpleMath=0;  // 1:  simple array arithmetics ( *,+), 0: do nothing
+  float scale = 1.0;
+  float offset = 0.0; // If SCALE and/or OFFSET are defined, then the data values are scaled as SCALE*(VALUE-OFFSET).
+                      // The default value for SCALE is 1.0; the default for OFFSET is 0.0.
+  double  missval;
+
+  cdoInitialize(argument);
+
+  int SELMULTI       = cdoOperatorAdd("selmulti",       0, 0, "filename/string with selection specification ");
+  int DELMULTI       = cdoOperatorAdd("delmulti",       0, 0, "filename/string with selection specification ");
+  int CHANGEMULTI    = cdoOperatorAdd("changemulti",    0, 0, "filename/string with selection specification ");
+
+  int operatorID = cdoOperatorID();
+
+  operatorInputArg(cdoOperatorEnter(operatorID));
+
+  char *filenameOrString;
+
+  //operatorCheckArgc(1);
+  filenameOrString = operatorArgv()[0];
+  if ( cdoDebugExt )
+    {
+      printf("Given operator arguments (nr=%d): \n", operatorArgc());
+      for (int i=0; i < operatorArgc(); i++)
+        printf("%s",operatorArgv()[i]);
+      printf("\n");
+    }
+  if (!multiSelectionParser(filenameOrString))
+    cdoWarning("Error processing file with selection description!\n%s",filenameOrString);
+
+  if (operatorID == SELMULTI)
+    if (getNumberOfSelectionTuples()==0)
+      cdoAbort("Error! You must provide at lease ONE selection tuple!\nNotations: 'SELECT,  .. or sel(/;;) or (/;;)'\nCheck the file: %s",filenameOrString);
+
+  if (operatorID == DELMULTI)
+    if (getNumberOfDeleteSelectionTuples()==0)
+      cdoAbort("Error! You must provide at lease ONE selection tuple!\nNotations: 'DELETE,  .. or del(/;;) or (/;;)'\nCheck the file: %s",filenameOrString);
+
+  if (operatorID == CHANGEMULTI)
+    if (getNumberOfSelectionTuples()==0)
+      cdoAbort("Error! You must provide at lease ONE selection tuple!\nNotations: 'CHANGE,  .. or (/;;|;;;)'\nCheck the file: %s",filenameOrString);
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int vlistID1 = streamInqVlist(streamID1);
+
+  vlistClearFlag(vlistID1);
+  int nvars = vlistNvars(vlistID1);
+
+  if ( cdoDebugExt ) cdoPrint(" Total number of variables: %d", nvars);
+
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      code    = vlistInqVarCode(vlistID1, varID);
+      zaxisID = vlistInqVarZaxis(vlistID1, varID);
+      ltype = zaxis2ltype(zaxisID);
+      nlevs   = zaxisInqSize(zaxisID);
+
+      for ( levelID = 0; levelID < nlevs; levelID++ )
+        {
+          double level = zaxisInqLevel(zaxisID, levelID);
+
+          if (operatorID == DELMULTI) vlistDefFlag(vlistID1, varID, levelID, TRUE); // set initially, override bellow if in selection
+          if (operatorID == CHANGEMULTI)
+            {
+              vlistDefFlag(vlistID1, varID, levelID, TRUE); // change operation copies all fields
+              continue;
+            }
+
+          for ( int ii=0; ii<NUMTUPLES; ii++ )
+            {
+              TUPLEREC *tuplerec = getSelTuple(ii);
+              //if ( cdoDebugExt ) cdoPrint(" Processing: (code %d, ltype %d, level %d);  nvars=%d, varID=%d", code, ltype, (int)level, nvars, varID);
+              // Note: When the list is Empty then function checkListContainsInt() also returns true !
+              selcode  = checkListContainsInt(code, tuplerec->codeLST, tuplerec->ncodes);
+              selltype = checkListContainsInt(ltype, tuplerec->levelTypeLST, tuplerec->nlevelTypes);
+              sellevel = checkListContainsInt((int)level, tuplerec->levelLST, tuplerec->nlevels);
+              if ( selcode && selltype && sellevel )
+                {
+                  if (operatorID == SELMULTI)
+                    {
+                      switch (tuplerec->sel_or_del_or_change)
+                        {
+                        case 0:   // operator decides ...
+                          vlistDefFlag(vlistID1, varID, levelID, TRUE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        case 1:
+                          vlistDefFlag(vlistID1, varID, levelID, TRUE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        case 2:
+                          vlistDefFlag(vlistID1, varID, levelID, FALSE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        }
+                    }
+                  else if (operatorID == DELMULTI)
+                    {
+                      switch (tuplerec->sel_or_del_or_change)
+                        {
+                        case 0:   // operator decides ...
+                          vlistDefFlag(vlistID1, varID, levelID, FALSE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        case 1:
+                          vlistDefFlag(vlistID1, varID, levelID, TRUE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting : (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        case 2:
+                          vlistDefFlag(vlistID1, varID, levelID, FALSE);
+                          if ( cdoDebugExt )
+                            {
+                              if (!tuplerec->simpleMath)
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]", code, ltype, (int)(level), varID, levelID);
+                              else
+                                cdoPrint(" Selecting for removal: (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f", code, ltype, (int)(level), varID, levelID, tuplerec->scale,tuplerec->offset);
+                            }
+                          break;
+                        }
+                    }
+                  break;
+                }
+            } //end for ( .. NUMTUPLES
+        } //end for ( levelID
+    } // end for ( varID
+
+  if ( cdoDebugExt ) cdoPrint(" Writing the selected fields ...");
+
+  int vlistID2 = vlistCreate();
+  vlistCopyFlag(vlistID2, vlistID1);
+
+  nvars = vlistNvars(vlistID2);
+  for ( varID = 0; varID < nvars; ++varID )
+    if ( vlistInqVarTsteptype(vlistID2, varID) != TSTEP_CONSTANT ) break;
+  if ( varID == nvars ) vlistDefNtsteps(vlistID2, 0);
+
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  int nrecs = vlistNrecs(vlistID2);
+
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+  streamDefVlist(streamID2, vlistID2);
+
+  int gridsize = vlistGridsizeMax(vlistID1);
+  if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
+  double *array = (double *) malloc(gridsize*sizeof(double));
+
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+      streamDefTimestep(streamID2, tsID);
+
+      for ( int recID = 0; recID < nrecs; recID++ )
+        {
+          streamInqRecord(streamID1, &varID, &levelID);
+          missval = vlistInqVarMissval(vlistID1, varID);
+
+          if ( vlistInqFlag(vlistID1, varID, levelID) == TRUE )
+            {
+              simpleMath=0;  // 1:  simple array arithmetics ( *,+), 0: do nothing
+              scale = 1.0;
+              offset = 0.0;
+              code    = vlistInqVarCode(vlistID1, varID);
+              zaxisID = vlistInqVarZaxis(vlistID1, varID);
+              double level = zaxisInqLevel(zaxisID, levelID);
+              ltype = zaxis2ltype(zaxisID);
+              for ( int ii=0; ii<NUMTUPLES; ii++ )
+                {
+                  TUPLEREC *tuplerec = getSelTuple(ii);
+                  // Note: When the list is Empty then function checkListContainsInt() also returns true !
+                  selcode  = checkListContainsInt(code, tuplerec->codeLST, tuplerec->ncodes);
+                  selltype = checkListContainsInt(ltype, tuplerec->levelTypeLST, tuplerec->nlevelTypes);
+                  sellevel = checkListContainsInt((int)level, tuplerec->levelLST, tuplerec->nlevels);
+                  lcopy = true;
+                  if ( selcode && selltype && sellevel )
+                    {
+                      if ( operatorID == CHANGEMULTI )
+                        {
+                          if ( cdoDebugExt )
+                            cdoPrint(" Processing: (code %d, ltype %d, level %d);  nvars=%d, varID=%d => (selcode %d, selltype %d, sellevel %d) => change (%d,%d,%d)",
+                                     code, ltype, (int)level, nvars, varID, selcode, selltype, sellevel, tuplerec->changedCode, tuplerec->changedLevelType, tuplerec->changedLevel);
+                          if ( (tuplerec->changedCode==-1) && (tuplerec->changedLevelType==-1) && (tuplerec->changedLevel==-1) )
+                            cdoPrint(" WARNING: Cannot CHANGE identification!");
+                          else
+                            streamGrbChangeParameterIdentification(tuplerec->changedCode, tuplerec->changedLevelType, tuplerec->changedLevel);
+                          // Calling PROXY function streamGrbChangeParameterIdentification()
+                          // which results in later calling func. gribapiChangeParameterIdentification(); see stream_gribapi.c
+                          // The change happens during the last step of writing a grib-record into a file.
+                        }
+                      else
+                        {
+                          if ( cdoDebugExt ) cdoPrint(" Processing: (code %d, ltype %d, level %d);  nvars=%d, varID=%d => (selcode %d, selltype %d, sellevel %d)", code, ltype, (int)level, nvars, varID, selcode, selltype, sellevel);
+                        }
+                      simpleMath = tuplerec->simpleMath;  // 1:  simple array arithmetics ( *,+), 0: do nothing
+                      if (simpleMath)
+                        {
+                          scale = tuplerec->scale;
+                          offset = tuplerec->offset;
+                          lcopy = false;
+                        }
+                      break; // get out of this for loop
+                    }
+                } // end of for (ii=0; ii<NUMTUPLES ..
+
+              varID2   = vlistFindVar(vlistID2, varID);
+              levelID2 = vlistFindLevel(vlistID2, varID, levelID);
+
+              // tijdelijk PATCH M.K.
+              if ((varID2==-1) || (levelID2==-1)) {
+                cdoPrint(" Warning: Missing varID or levelID with (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)] .. #2[varID(%d),levelID(%d)]",code, ltype, (int)(level), varID,levelID, varID2, levelID2);
+                continue;
+              }
+              streamDefRecord(streamID2, varID2, levelID2);
+
+              if ( lcopy )
+                {
+                  if ( cdoDebugExt ) cdoPrint(" Copying record [%4d] with (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]",recID, code, ltype, (int)(level), varID,levelID);
+                  streamCopyRecord(streamID2, streamID1);
+                }
+              else
+                {
+                  streamReadRecord(streamID1, array, &nmiss);
+
+                  if (!simpleMath)
+                    {
+                      if ( cdoDebugExt ) cdoPrint(" Writing record [%4d] with (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]",recID, code, ltype, (int)(level), varID,levelID);
+                      streamWriteRecord(streamID2, array, nmiss);
+                    }
+                  else  // 1:  simple array arithmetics ( *,+)
+                    {
+                      if ( cdoDebugExt ) cdoPrint(" Writing record [%4d] with (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]; SCALE=%f; OFFSET=%f",recID, code, ltype, (int)(level), varID,levelID,scale,offset);
+                      for ( int li = 0; li < gridsize; ++li )
+                        if (! DBL_IS_EQUAL(array[li], missval) )
+                          {
+                            array[li] = scale*(array[li] - offset);
+                            // If SCALE and/or OFFSET are defined, then the data values are scaled as SCALE*(VALUE-OFFSET).
+                          }
+                      streamWriteRecord(streamID2, array, nmiss);
+                    }
+                } // end of else ( lcopy )
+            } // end if ( vlistInqFlag(vlistID1, varID, levelID) == TRUE )
+        } // end for ( recID ..
+
+      /*if ( vlistInqFlag(vlistID1, varID, levelID) == FALSE )
+        if (operatorID == DELMULTI)
+        {
+        code    = vlistInqVarCode(vlistID1, varID);
+        zaxisID = vlistInqVarZaxis(vlistID1, varID);
+        level = zaxisInqLevel(zaxisID, levelID);
+        ltype = zaxis2ltype(zaxisID);
+        if ( cdoDebugExt ) cdoPrint(" Removing record [%4d] with (code %3i, ltype %3i, level %3i)   [varID(%d),levelID(%d)]",recID, code, ltype, (int)(level), varID, levelID);
+        }
+        else*/
+
+      tsID++;
+    } // end while ( (nrecs
+
+  streamClose(streamID1);
+  streamClose(streamID2);
+
+  vlistDestroy(vlistID2);
+
+  if ( ! lcopy )
+    if ( array ) free(array);
+
+  cdoFinish();
+
+  cdoDebugExt = 0;
+
+  return 0;
+}
+
+
+TUPLEREC *TUPLERECNew()
+{
+  TUPLEREC *tpl = (TUPLEREC *) malloc(sizeof(TUPLEREC));
+
+  tpl->codeLST = lista_new(INT_LISTA);
+  tpl->ncodes = 0;
+
+  tpl->levelTypeLST = lista_new(INT_LISTA);
+  tpl->nlevelTypes = 0;
+
+  tpl->levelLST = lista_new(INT_LISTA);
+  tpl->nlevels = 0;
+  tpl->sel_or_del_or_change = 0; // sel_or_del_or_change:  0:  operator decides, 1:select , 2:delete, 3:change
+
+  tpl->simpleMath= 0;  // 1:  simple array arithmetics ( *,+), 0: do nothing
+  tpl->scale = 1.0;
+  tpl->offset = 0.0;
+
+  tpl->changedCode = -1;    // used only changemulti mode
+  tpl->changedLevelType = -1;
+  tpl->changedLevel = -1;
+
+  return tpl;
+}
+
+void push_backSelTuple(TUPLEREC *tp)
+{
+ if (NUMTUPLES<MAX_TUPLES) {
+  SelTUPLEREC[NUMTUPLES] = tp;
+  NUMTUPLES++;
+ }
+}
+
+TUPLEREC * getSelTuple(int index)
+{
+ if (index<NUMTUPLES) {
+  return SelTUPLEREC[index];
+ }
+ return NULL;
+}
+
+int push_backIntList(int value, lista_t *list, int arraylen)
+{
+  lista_set_int(list, arraylen, value);
+  arraylen +=1;
+  return arraylen;
+}
+
+int checkListContainsInt(int value, lista_t *list, int arraylen)
+// Note: When the list is Empty it also returns true !
+{
+ int i;
+ int *array = (int *) lista_dataptr(list);
+
+ if (arraylen==0) {
+        //if ( cdoDebugExt ) cdoPrint(" value=%d: found. (list empty)");
+        return 1;
+ }
+ for (i=0; i<arraylen; i++)
+ {
+   if (array[i]==-1) {  // this is for '*' selection; can be any code, any level or any level-type
+        //if ( cdoDebugExt ) cdoPrint(" value=%d: found.");
+        return 1;
+   }
+
+   if (array[i]==value) {
+        //if ( cdoDebugExt ) cdoPrint(" value=%d: found.");
+        return 1;
+   }
+ }
+ //if ( cdoDebugExt ) cdoPrint(" value=%d: NOT found.");
+ return 0;
+}
+
+
+int getIntFromList(int index, lista_t *list, int arraylen)
+{
+  int *array = (int *) lista_dataptr(list);
+  if (index <arraylen)
+    return array[index];
+  else
+    return -999;
+}
+
+
+
+
+
+#define MAX_LINE_LEN 65536
+
+static
+char *removeSpaces(char *pline)
+{
+  if (pline==NULL) return NULL;
+  while ( isspace((int) *pline) ) pline++;
+  return pline;
+}
+
+
+static
+char *skipSeparator(char *pline)
+{
+  if (pline==NULL) return NULL;
+  while ( isspace((int) *pline) ) pline++;
+  if ( *pline == '=' || *pline == ':' || *pline == '/' || *pline == ',' ) pline++;
+  while ( isspace((int) *pline) ) pline++;
+  return pline;
+}
+
+
+static
+char *goToNextSeparator(char *pline)
+{
+  if (pline==NULL) return NULL;
+  int separatorFound =0;
+  while ( isspace((int) *pline) || !separatorFound)
+  {
+        if (*pline=='\0') return NULL;
+        pline++;
+        if (*pline == '|') return NULL;
+        if ( *pline == '=' || *pline == ':' || *pline == '/' || *pline == ',' )
+                separatorFound = 1;
+        else
+            if ( *pline == ';')
+            { pline++;
+              pline = removeSpaces(pline);
+              return (pline);
+            }
+  }
+  if (separatorFound) pline++;
+  if ( cdoDebugExt>=100 ) cdoPrint("goToNextSeparator():  pline= ('%s') ", pline);
+  //while ( isspace((int) *pline) ) pline++;
+  pline = removeSpaces(pline);
+  return pline;
+}
+
+
+static
+char *strContains(char *str, const char *substr)
+{
+  if (str==NULL) return NULL;
+  if (substr==NULL) return NULL;
+
+  str = removeSpaces(str);
+
+  size_t lensub = strlen(substr);
+  size_t lenstr = strlen(str);
+
+  if (lensub>lenstr) {
+        if ( cdoDebugExt>=100 ) cdoPrint("strContains():  substr('%s') NOT found in str('%s');  lensub(%d)>lenstr(%d) ", substr,str, lensub,lenstr);
+        return NULL;
+  }
+  char *rv = strstr(str, substr);
+  if (rv) {
+        if ( cdoDebugExt>=100 ) cdoPrint("strContains():  substr('%s') FOUND in str('%s')", substr,str);
+        return (rv+lensub);   // points after subStr ..
+  }
+  else {
+        if ( cdoDebugExt>=100 ) cdoPrint("strContains():  substr('%s') NOT found in str('%s')", substr,str);
+        return rv;
+ }
+}
+
+static
+char *findParamEnd(char *str)
+{
+  char *ptr = str;
+  char *ptrEnding=NULL;
+
+  if (str==NULL) return NULL;
+  // supported endings are: ", " or ";"
+  if (ptrEnding==NULL) ptrEnding = strContains(ptr,", "); // HIP notation
+  if (ptrEnding==NULL) ptrEnding = strContains(ptr,";");  // compact notation
+  if (ptrEnding!=NULL) {
+          ptrEnding = removeSpaces(ptrEnding);
+          if ( cdoDebugExt>=100 ) cdoPrint(" ptrEnding='%s'", ptrEnding);
+          return ptrEnding;
+  }
+  if ( cdoDebugExt>=100 ) cdoPrint(" ptrEnding=end-of-string");
+  size_t lenstr = strlen(str);
+  ptrEnding = str+lenstr;
+  ptrEnding = removeSpaces(ptrEnding);
+  return ptrEnding;
+}
+
+static
+char *findTupleEnd(char *str)
+{
+  char *ptr = str;
+  char *ptrEnding;
+
+  if (str==NULL) return NULL;
+  // supported endings are: ")" or ");"
+  ptrEnding = strContains(ptr,")");
+  if (ptrEnding==NULL) ptrEnding = strContains(ptr,");");
+  if (ptrEnding!=NULL) {
+          ptrEnding = removeSpaces(ptrEnding);
+          if ( cdoDebugExt>=100 ) cdoPrint(" findTupleEnd='%s'", ptrEnding);
+          return ptrEnding;
+  }
+  if ( cdoDebugExt>=100 ) cdoPrint(" findTupleEnd=end-of-string");
+  size_t lenstr = strlen(str);
+  ptrEnding = str+lenstr;
+  ptrEnding = removeSpaces(ptrEnding);
+  return ptrEnding;
+}
+
+static
+char *readlineForParsing(FILE *gfp, char *strToParsePtr, char *line)
+{
+  if ( gfp != NULL ) // file is open => we parse text from a file
+    {
+      int status = readline(gfp, line, MAX_LINE_LEN);
+      return (status == 0) ? NULL : line;
+    }
+  else
+    if (strToParsePtr!=NULL)  // we parse a given string
+      {
+        if ( cdoDebugExt>=30 ) cdoPrint("%s(): Parsing selection string:  %s", __func__, strToParsePtr);
+        char *tpEnd = NULL;
+        if (strlen(strToParsePtr)>0)
+          tpEnd = findTupleEnd(strToParsePtr);
+        if (tpEnd==NULL)
+          {
+            if ( cdoDebugExt>=100 ) cdoPrint("%s(): End of selection string reached.", __func__);
+            return NULL;
+          }
+        else
+          {
+            tpEnd[0] = 0;
+            if (strlen(strToParsePtr)<=MAX_LINE_LEN)
+              strcpy(line,strToParsePtr);
+            if ( cdoDebugExt>=100) cdoPrint("%s(): Current selection line=%s", __func__, line);
+            strToParsePtr = tpEnd +1;
+            return strToParsePtr;
+          }
+      }
+    else
+      {
+        cdoAbort(" Cannot parse selection string:  %s", strToParsePtr);
+        return NULL;
+      }
+}
+
+int multiSelectionParser(const char *filenameOrString)
+{
+  char line[MAX_LINE_LEN], *pline;
+  char *strpos;
+  char *parEnd;
+  int val;
+  float floatval;
+  TUPLEREC *tuplerec;
+  int selectionRec;
+  FILE *gfp = NULL;
+  char strToParse[MAX_LINE_LEN];
+  char *strToParsePtr = NULL; strToParse[0]=0;
+  int convertLevelsHPa2Pa = 0;  // this is HIP - KNMI selection specific
+  char first3chars[4];
+  strncpy(first3chars,filenameOrString,3);
+  
+  if ( (filenameOrString[0]=='{') || (filenameOrString[0]=='(') || strContains(first3chars, "del") || strContains(first3chars, "sel") )
+  {
+      // cdo selmulti,'(33/34;105;10)'
+      // - or -
+      // cdo selmulti,'{(33/34;105;10);(11/32,8;109;51/52/53/54/55)}'
+      // - or -
+      // cdo changemulti,'{(134;1;0|1;105;0);(6;1;0|6;105;0)}'
+      strncpy(strToParse,filenameOrString,MAX_LINE_LEN);
+      strToParsePtr = &strToParse[0];
+      if (strToParsePtr[0]=='{')
+          strToParsePtr++;
+      int strLn = strlen(strToParsePtr);
+      if (strToParsePtr[strLn-1]=='}')
+        strToParsePtr[strLn-1] = 0;
+      if ( cdoDebugExt ) cdoPrint(" Parsing selection string:  %s", strToParsePtr);
+  }
+  else
+  {
+      gfp = fopen(filenameOrString, "r");
+      if ( cdoDebugExt ) cdoPrint(" Parsing file:  %s", filenameOrString);
+      if (gfp==NULL)
+      {
+        cdoAbort(" Missing file:  %s", filenameOrString);
+        return 0;
+      }
+  }
+
+  while ( (strToParsePtr = readlineForParsing(gfp, strToParsePtr, line)) )
+  {
+      if ( line[0] == '#' ) continue;
+      if ( line[0] == '\0' ) continue;
+      pline = line;
+      if ( cdoDebugExt>=30 ) cdoPrint(": Line: %s", pline);
+      while ( isspace((int) *pline) ) pline++;
+      if ( pline[0] == '\0' ) continue;
+      strpos=strContains(pline, "SELECT, ");
+      selectionRec = 0; // default is 0;  sel_or_del_or_change:  0:  operator decides, 1:select , 2:delete, 3:change
+      if ( strpos != NULL ) selectionRec = 1;
+      else {
+               strpos=strContains(pline, "DELETE, ");
+              if ( strpos != NULL ) selectionRec = 2;
+              else {
+                      strpos=strContains(pline, "REMOVE, ");
+                      if ( strpos != NULL ) selectionRec = 2;
+                   }
+            }
+      if (strpos!= NULL ) // we have SELECT ..
+      {
+          if ( cdoDebugExt ) cdoPrint(" Parsing notation SELECT: %s", strpos);
+          pline = strpos;
+          tuplerec = TUPLERECNew();
+          tuplerec->sel_or_del_or_change = selectionRec;
+          push_backSelTuple(tuplerec);
+          // SELECT, PARAMETER=11/17, LEVTYPE=105, LEVEL=2
+          while ( (pline!=NULL) && (strlen(pline)!=0) )
+          {     if ( cdoDebugExt>=100 ) cdoPrint("pline='%s'", pline);
+                strpos=strContains(pline, "PARAMETER=");
+                if ( (strpos) != NULL )
+                {
+                  if ( cdoDebugExt>=100 ) cdoPrint(": PARAMETER=%s", strpos);
+                  pline = strpos;
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("code=%d",val);
+                        tuplerec->ncodes = push_backIntList(val, tuplerec->codeLST, tuplerec->ncodes);
+                        strpos = goToNextSeparator(pline);
+                        pline = strpos;
+                        if (!strpos) break;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                if ( cdoDebugExt>=100 ) cdoPrint("pline='%s'", pline);
+                strpos=strContains(pline, "LEVTYPE=");
+                if ( (strpos) != NULL )
+                {
+                  if ( cdoDebugExt>=100 ) cdoPrint(": LEVTYPE=%s", strpos);
+                  pline = strpos;
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd) && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if (val==100)
+                        {  convertLevelsHPa2Pa = 1;
+                           if ( cdoDebugExt>=1 ) cdoPrint("Detected levelType=100 ! HIP selection specifies HPa but CDO has levels in Pascals.\nSelection HPa's will be converted into Pa's.");
+                        } else convertLevelsHPa2Pa = 0;
+                        if ( cdoDebugExt>=100 ) cdoPrint("levelType=%d",val);
+                        tuplerec->nlevelTypes = push_backIntList(val, tuplerec->levelTypeLST, tuplerec->nlevelTypes);
+                        strpos = goToNextSeparator(pline);
+                        pline = strpos;
+                        if (!strpos) break;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                if ( cdoDebugExt>=100 ) cdoPrint("pline='%s'", pline);
+                strpos=strContains(pline, "LEVEL=");
+                if ( (strpos) != NULL )
+                {
+                  if ( cdoDebugExt>=100 ) cdoPrint(": LEVEL=%s", strpos);
+                  pline = strpos;
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if ((convertLevelsHPa2Pa) && (val!=-1) )
+                        {
+                            val*=100;
+                        }
+                        if ( cdoDebugExt>=100 ) cdoPrint("level=%d",val);
+                        tuplerec->nlevels = push_backIntList(val, tuplerec->levelLST, tuplerec->nlevels);
+                        strpos = goToNextSeparator(pline);
+                        pline = strpos;
+                        if (!strpos) break;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                if ( cdoDebugExt>=100 ) cdoPrint("pline='%s' (check SCALE=...)", pline);
+                strpos=strContains(pline, "SCALE=");
+                if ( (strpos) != NULL )
+                {
+                  if ( cdoDebugExt>=100 ) cdoPrint(": SCALE= %s", strpos);
+                  pline = strpos;
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        floatval = atof(pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("scale=%f",floatval);
+                        tuplerec->simpleMath=1; // 1:  simple array arithmetics ( *,+), 0: do nothing
+                        tuplerec->scale = floatval;  //tuplerec->offset = 0.0;
+                        strpos = goToNextSeparator(pline);
+                        pline = strpos;
+                        if (!strpos) break;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                if ( cdoDebugExt>=100 ) cdoPrint("pline='%s' (check OFFSET=...)", pline);
+                strpos=strContains(pline, "OFFSET=");
+                if ( (strpos) != NULL )
+                {
+                  if ( cdoDebugExt>=100 ) cdoPrint(": OFFSET= %s", strpos);
+                  pline = strpos;
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        floatval = atof(pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("offset=%f",floatval);
+                        tuplerec->simpleMath=1; // 1:  simple array arithmetics ( *,+), 0: do nothing
+                        tuplerec->offset = floatval; // tuplerec->scale = 1.0;
+                        strpos = goToNextSeparator(pline);
+                        pline = strpos;
+                        if (!strpos) break;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+          } // end while pline
+          continue;
+      } // end if SELECT,
+
+      // Here comes the short notation
+      selectionRec = 0; // default is 0;  sel_or_del_or_change:  0:  operator decides, 1:select , 2:delete, 3:change
+      strpos=strContains(pline, "sel(");
+      if ( strpos != NULL ) selectionRec = 1;
+      else {
+              strpos=strContains(pline, "del(");
+              if ( strpos != NULL ) selectionRec = 2;
+              else {
+                  strpos=strContains(pline, "|");
+                  if ( strpos != NULL ) selectionRec = 3;
+                  else {
+                          strpos=strContains(pline, "(");
+                          if ( strpos != NULL ) selectionRec = 0;
+                      }
+              }
+           }
+      if ( strpos != NULL )
+        {
+          if ( cdoDebugExt ) cdoPrint(" Parsing notation (code(s),..; levelType(s),..; level(s),..) : %s; [selectionRec =%d]", strpos, selectionRec );
+          if (selectionRec == 3)
+              strpos = strContains(pline, "(");
+          pline = strpos;
+          tuplerec = TUPLERECNew();
+          tuplerec->sel_or_del_or_change = selectionRec;
+          push_backSelTuple(tuplerec);
+          // (33/34; 105; 10)
+          while ( (pline!=NULL) && (strlen(pline)!=0) && (pline[0]!=')') )
+          {     if ( cdoDebugExt>=100 ) cdoPrint("[1]: pline='%s'", pline);
+                // 1st is code
+                {
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("code=%d",val);
+                        tuplerec->ncodes = push_backIntList(val, tuplerec->codeLST, tuplerec->ncodes);
+                        strpos = goToNextSeparator(pline);
+                        if (!strpos) { pline=parEnd; break;} else pline = strpos;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                // 2nd is level type
+                if ( cdoDebugExt>=100 ) cdoPrint("[2]: pline='%s'", pline);
+                {
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if (val==100)
+                        {  convertLevelsHPa2Pa = 1;
+                           if ( cdoDebugExt>=1 ) cdoPrint("Detected levelType=100 ! Selection specifies HPa but CDO has levels in Pascals.\nSelection HPa's will be converted into Pa's.");
+                        } else convertLevelsHPa2Pa = 0;
+
+                        if ( cdoDebugExt>=100 ) cdoPrint("levelType=%d",val);
+                        tuplerec->nlevelTypes  =push_backIntList(val, tuplerec->levelTypeLST, tuplerec->nlevelTypes);
+                        strpos = goToNextSeparator(pline);
+                        if (!strpos) { pline=parEnd; break;} else pline = strpos;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+                // 3rd is level
+                if ( cdoDebugExt>=100 ) cdoPrint("[3]: pline='%s'", pline);
+                {
+                  pline = removeSpaces(pline);
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if ((convertLevelsHPa2Pa) && (val!=-1) )
+                        {
+                            val*=100;
+                        }
+                        if ( cdoDebugExt>=100 ) cdoPrint("level=%d",val);
+                        tuplerec->nlevels = push_backIntList(val, tuplerec->levelLST, tuplerec->nlevels);
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        strpos = goToNextSeparator(pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if (!strpos) {
+                            strpos = strContains(pline,"|");  // compact notation for  changemulti
+                            if (strpos)  pline=strpos-1; // strContains returns character after...
+                                   else  pline=parEnd;
+                            if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                            break;
+                            }
+                        else pline = strpos;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+
+                // OPTIONAL:
+                // cdo changemulti,'{(134;1;*|1;105;*);{(6;1;*|6;105;*)};{(246;*;*|76;*;*)};{(247;*;*|58;*;*)};{(248;*;*|71;*;*)}' fileIN fileOUT
+                if ( cdoDebugExt>=100 ) cdoPrint("[OPT]: pline='%s'", pline);
+                {
+                  pline = removeSpaces(pline);
+                  // pline points to: "=1;105;*);....."
+                  if (pline[0]=='|')
+                  {     // changemulti specification
+                        tuplerec->sel_or_del_or_change = 3;
+                        pline =  &pline[1];
+                        // Get changedCode:
+                        parEnd = findParamEnd(pline);
+                        if ( (!parEnd) || (pline[0]==0))
+                                cdoAbort("Channot parse: strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        tuplerec->changedCode = val;
+                        if ( cdoDebugExt>=100 ) cdoPrint("changedCode=%d",val);
+                        strpos = goToNextSeparator(pline);
+                        if (!strpos)
+                            cdoAbort("Channot parse: strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        pline = skipSeparator(strpos);
+                        // Get changedLevelType:
+                        parEnd = findParamEnd(pline);
+                        if ( (!parEnd) || (pline[0]==0))
+                                cdoAbort("Channot parse: strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        tuplerec->changedLevelType = val;
+                        if ( cdoDebugExt>=100 ) cdoPrint("changedLevelType=%d",val);
+                        strpos = goToNextSeparator(pline);
+                        if (!strpos)
+                            cdoAbort("Channot parse: strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        pline = skipSeparator(strpos);
+                        // Get changedLevel:
+                        parEnd = findParamEnd(pline);
+                        if ( (!parEnd) || (pline[0]==0))
+                                cdoAbort("Channot parse: strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        tuplerec->changedLevel = val;
+                        if ( cdoDebugExt>=100 ) cdoPrint("changedLevel=%d",val);
+                        pline=parEnd;
+                  }// changemulti specification
+                  parEnd = findParamEnd(pline);
+                  if ((!parEnd) && (!pline))
+                        if ( cdoDebugExt>=100 ) cdoPrint("strpos=%s; parEnd=%s ... pline=%s", strpos, parEnd,pline);
+                  while ( (pline!=parEnd)  && (strlen(pline)>0))
+                  {
+                        pline = removeSpaces(pline);
+                        if (pline[0]=='*') val=-1; else val = atoi(pline);
+                        if ((convertLevelsHPa2Pa) && (val!=-1) )
+                        {
+                            val*=100;
+                        }
+                        if ( cdoDebugExt>=100 ) cdoPrint("level=%d",val);
+                        tuplerec->nlevels = push_backIntList(val, tuplerec->levelLST, tuplerec->nlevels);
+                        strpos = goToNextSeparator(pline);
+                        if (!strpos) { pline=parEnd; break;} else pline = strpos;
+                        pline = skipSeparator(strpos);
+                  }
+                }
+
+
+          } // end while pline
+       } // end if "("
+  } // end while ( readline(gfp, line, MAX_LINE_LEN) )
+  if (gfp!=NULL)
+      fclose(gfp);
+
+  printSelectionTuples();
+  return 1;
+
+}
+
+
+void printSelectionTuples()
+{
+  if ( cdoDebugExt ) cdoPrint(" Printing selection tuples:");
+
+  int ii, ri;
+  for (ii=0; ii<NUMTUPLES; ii++)
+  {
+        TUPLEREC *tuplerec = getSelTuple(ii);
+        char strval[1000]; strcpy(strval,"(");
+        char bff[200]; bff[0]='\0';
+        if ( cdoDebugExt ) cdoPrint(" Selection tuple [%d]: ncodes=%d, nlevelTypes=%d, nlevels=%d",ii,tuplerec->ncodes,tuplerec->nlevelTypes,tuplerec->nlevels);
+        for (ri=0; ri< tuplerec->ncodes; ri++)
+        {
+                 sprintf(bff,"%d", lista_get_int(tuplerec->codeLST, ri) );
+                 strcat(strval,bff);
+                 if ( (ri+1)< tuplerec->ncodes )
+                        strcat(strval,"/");
+                 else    strcat(strval,";");
+        }
+        for (ri=0; ri< tuplerec->nlevelTypes; ri++)
+        {
+                 sprintf(bff,"%d", lista_get_int(tuplerec->levelTypeLST, ri) );
+                 strcat(strval,bff);
+                 if ( (ri+1)< tuplerec->nlevelTypes )
+                        strcat(strval,"/");
+                 else    strcat(strval,";");
+        }
+        for (ri=0; ri< tuplerec->nlevels; ri++)
+        {
+                 sprintf(bff,"%d", lista_get_int(tuplerec->levelLST, ri) );
+                 strcat(strval,bff);
+                 if ( (ri+1)< tuplerec->nlevels )
+                        strcat(strval,"/");
+                 else    strcat(strval,")");
+        }
+
+
+        if (tuplerec->simpleMath)
+        {
+            sprintf(bff," {scale = %f; offset = %f}",tuplerec->scale, tuplerec->offset);
+            strcat(strval,bff);
+        }
+
+        // sel_or_del_or_change:  0:  operator decides, 1:select , 2:delete, 3:change
+        if (tuplerec->sel_or_del_or_change==1)
+        {
+            if ( cdoDebugExt ) cdoPrint(" Selection tuple [%d] = %s (select)",ii,strval);
+        }
+        else
+        if (tuplerec->sel_or_del_or_change==2)
+        {
+            if ( cdoDebugExt ) cdoPrint(" Selection tuple [%d] = %s (delete)",ii,strval);
+        }
+        if (tuplerec->sel_or_del_or_change==3)
+        {
+            if ( cdoDebugExt ) cdoPrint(" Selection tuple [%d] = %s (change) => (%d; %d;%d;)",ii,strval,tuplerec->changedCode,tuplerec->changedLevelType,tuplerec->changedLevel);
+        }
+        else
+            cdoPrint(" Selection tuple [%d] = %s (select/delete)",ii,strval);
+  }
+}
+
+
+int getNumberOfSelectionTuples()
+{
+  int ii;
+  int nn=0;
+  for (ii=0; ii<NUMTUPLES; ii++)
+  {
+        TUPLEREC *tuplerec = getSelTuple(ii);
+        if (tuplerec->sel_or_del_or_change!=2) nn++;
+  }
+  return nn;
+}
+
+int getNumberOfDeleteSelectionTuples()
+{
+  int ii;
+  int nn=0;
+  cdoPrint("NUMTUPLES = %d",NUMTUPLES);
+  printSelectionTuples();
+  for (ii=0; ii<NUMTUPLES; ii++)
+  {
+        TUPLEREC *tuplerec = getSelTuple(ii);
+        cdoPrint("getNumberOfDeleteSelectionTuples() [%d]=%d\n", ii, tuplerec->sel_or_del_or_change);
+        if (tuplerec->sel_or_del_or_change!=1) nn++;
+  }
+  return nn;
+}
diff --git a/src/Selrec.c b/src/Selrec.c
index 1213e2f..93ddd30 100644
--- a/src/Selrec.c
+++ b/src/Selrec.c
@@ -22,11 +22,8 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"  /* processSelf */
 #include "pstream.h"
-#include "error.h"
-#include "util.h"
 #include "listarray.h"
 
 
diff --git a/src/Seltime.c b/src/Seltime.c
index a4d58fa..33c7d67 100644
--- a/src/Seltime.c
+++ b/src/Seltime.c
@@ -31,11 +31,8 @@
 
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include "error.h"
-#include "util.h"
 #include "listarray.h"
 
 
@@ -53,8 +50,10 @@ void season_to_months(const char *season, int *imonths)
   else
     {
       if ( len > 12 ) cdoAbort("Too many months %d (limit=12)!", (int)len);
-      //      char *sstr = strcasestr(smons, season); // nonstandard extension
-      const char *sstr = strstr(smons, season);
+      char *season_u = strdup(season);
+      strtoupper(season_u);
+      const char *sstr = strstr(smons, season_u);
+      free(season_u);
       if ( sstr == NULL ) cdoAbort("Season %s not available!", season);
       size_t ks = (size_t)(sstr-smons);
       size_t ke = ks + len;
diff --git a/src/Selvar.c b/src/Selvar.c
index 87859da..6fb3d95 100644
--- a/src/Selvar.c
+++ b/src/Selvar.c
@@ -35,11 +35,8 @@
 
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "pstream.h"
-#include "error.h"
-#include "util.h"
 #include "listarray.h"
 
 
diff --git a/src/Setgrid.c b/src/Setgrid.c
index 47b4392..5fcf58f 100644
--- a/src/Setgrid.c
+++ b/src/Setgrid.c
@@ -38,7 +38,6 @@ void *Setgrid(void *argument)
   int gridID2 = -1;
   int gridtype = -1;
   int nmiss;
-  int gridsize;
   int areasize = 0;
   int  masksize = 0;
   bool lregular = false;
@@ -62,6 +61,7 @@ void *Setgrid(void *argument)
   int UNSETGRIDMASK = cdoOperatorAdd("unsetgridmask", 0, 0, NULL);
   int SETGRIDNUMBER = cdoOperatorAdd("setgridnumber", 0, 0, "grid number and optionally grid position");
   int SETGRIDURI    = cdoOperatorAdd("setgriduri",    0, 0, "reference URI of the horizontal grid");
+  int USEGRIDNUMBER = cdoOperatorAdd("usegridnumber", 0, 0, "use existing grid identified by grid number");
 
   int operatorID = cdoOperatorID();
 
@@ -152,6 +152,11 @@ void *Setgrid(void *argument)
       for ( int i = 0; i < masksize; i++ )
 	if ( DBL_IS_EQUAL(gridmask[i], missval) ) gridmask[i] = 0;
     }
+  else if ( operatorID == USEGRIDNUMBER )
+    {
+      operatorCheckArgc(1);
+      number = parameter2int(operatorArgv()[0]);
+    }
   else if ( operatorID == SETGRIDNUMBER )
     {
       if ( operatorArgc() >= 1 && operatorArgc() <= 2 )
@@ -195,18 +200,25 @@ void *Setgrid(void *argument)
 	}
       if ( ! found ) cdoWarning("No grid with %d points found!", gridInqSize(gridID2));
     }
-  else if ( operatorID == SETGRIDNUMBER || operatorID == SETGRIDURI )
+  else if ( operatorID == SETGRIDNUMBER || operatorID == SETGRIDURI || operatorID == USEGRIDNUMBER )
     {
-      int gridID1 = vlistGrid(vlistID1, 0);
-
       if ( operatorID == SETGRIDNUMBER )
 	{
+          int gridID1 = vlistGrid(vlistID1, 0);
 	  gridID2 = gridCreate(GRID_UNSTRUCTURED, gridInqSize(gridID1));
 	  gridDefNumber(gridID2, number);
 	  gridDefPosition(gridID2, position);
 	}
+      else if ( operatorID == USEGRIDNUMBER ) 
+        {
+	  if ( number < 1 || number > vlistNgrids(vlistID1) )
+	    cdoAbort("Invalid grid number: %d (max = %d)!", number, vlistNgrids(vlistID1));
+          
+	  gridID2 = vlistGrid(vlistID1, number-1);
+        }
       else
 	{
+          int gridID1 = vlistGrid(vlistID1, 0);
 	  gridID2 = gridDuplicate(gridID1);
 	  gridDefReference(gridID2, griduri);
 	}
@@ -215,7 +227,7 @@ void *Setgrid(void *argument)
       int ngrids = vlistNgrids(vlistID1);
       for ( int index = 0; index < ngrids; index++ )
 	{
-	  gridID1 = vlistGrid(vlistID1, index);
+	  int gridID1 = vlistGrid(vlistID1, index);
 
 	  if ( gridInqSize(gridID1) == gridInqSize(gridID2) )
 	    {
@@ -310,7 +322,7 @@ void *Setgrid(void *argument)
       for ( int index = 0; index < ngrids; index++ )
 	{
 	  int gridID1  = vlistGrid(vlistID1, index);
-	  gridsize = gridInqSize(gridID1);
+	  int gridsize = gridInqSize(gridID1);
 	  if ( gridsize == areasize )
 	    {
 	      gridID2 = gridDuplicate(gridID1);
@@ -325,7 +337,7 @@ void *Setgrid(void *argument)
       for ( int index = 0; index < ngrids; index++ )
 	{
 	  int gridID1  = vlistGrid(vlistID1, index);
-	  gridsize = gridInqSize(gridID1);
+	  int gridsize = gridInqSize(gridID1);
 	  if ( gridsize == masksize )
 	    {
 	      int *mask = (int*) Malloc(masksize*sizeof(int));
@@ -360,10 +372,7 @@ void *Setgrid(void *argument)
   streamDefVlist(streamID2, vlistID2);
   //vlistPrint(vlistID2);
 
-  if ( lregular || lregularnn )
-    gridsize = vlistGridsizeMax(vlistID2);
-  else
-    gridsize = vlistGridsizeMax(vlistID1);
+  int gridsize = (lregular || lregularnn) ? vlistGridsizeMax(vlistID2) : vlistGridsizeMax(vlistID1);
 
   if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
   double *array = (double*) Malloc(gridsize*sizeof(double));
@@ -395,7 +404,7 @@ void *Setgrid(void *argument)
 	    }
 	  else if ( gridInqType(gridID1) == GRID_GME )
 	    {
-	      gridsize = gridInqSize(gridID1);
+	      int gridsize = gridInqSize(gridID1);
 	      int j = 0;
 	      for ( int i = 0; i < gridsize; i++ )
 		if ( grid2_vgpm[i] ) array[j++] = array[i];
diff --git a/src/Settime.c b/src/Settime.c
index c2bcf0b..e0b5ea1 100644
--- a/src/Settime.c
+++ b/src/Settime.c
@@ -66,13 +66,12 @@ int get_tunits(const char *unit, int *incperiod, int *incunit, int *tunit)
 static
 void shifttime(int calendar, int tunit, int ijulinc, int *pdate, int *ptime)
 {
-  int year, month, day;
   int vdate = *pdate;
   int vtime = *ptime;
-  juldate_t juldate;
 
   if ( tunit == TUNIT_MONTH || tunit == TUNIT_YEAR )
     {
+      int year, month, day;
       cdiDecodeDate(vdate, &year, &month, &day);
 	      
       month += ijulinc;
@@ -86,6 +85,7 @@ void shifttime(int calendar, int tunit, int ijulinc, int *pdate, int *ptime)
     }
   else
     {
+      juldate_t juldate;
       juldate = juldate_encode(calendar, vdate, vtime);
       juldate = juldate_add_seconds(ijulinc, juldate);
       juldate_decode(calendar, juldate, &vdate, &vtime);
diff --git a/src/Showinfo.c b/src/Showinfo.c
index f0f6a5c..17e4814 100644
--- a/src/Showinfo.c
+++ b/src/Showinfo.c
@@ -41,11 +41,7 @@
 
 void *Showinfo(void *argument)
 {
-  int zaxisID;
-  int vdate, vtime;
   int nrecs;
-  int nlevs, levelID;
-  int ltype;
   int date0 = 0;
   int year, month, day;
   int month0 = 0, year0 = 0;
@@ -65,6 +61,7 @@ void *Showinfo(void *argument)
   int SHOWLEVEL     = cdoOperatorAdd("showlevel",     0, 0, NULL);
   int SHOWLTYPE     = cdoOperatorAdd("showltype",     0, 0, NULL);
   int SHOWFORMAT    = cdoOperatorAdd("showformat",    0, 0, NULL);
+  int SHOWGRID      = cdoOperatorAdd("showgrid",      0, 0, NULL); 
 
   int operatorID = cdoOperatorID();
 
@@ -78,21 +75,18 @@ void *Showinfo(void *argument)
 
   if ( operatorID == SHOWYEAR )
     {
-      // int nyear = 0;
       int tsID = 0;
       if ( ntsteps != 0 )
 	while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	  {
-	    vdate = taxisInqVdate(taxisID);
+	    int vdate = taxisInqVdate(taxisID);
 
 	    cdiDecodeDate(vdate, &year, &month, &day);
 	 
 	    if ( tsID == 0 || year0 != year )
 	      {
-		// if ( nyear == 10 ) { nyear = 0; fprintf(stdout, "\n"); }
 		year0 = year;
 		fprintf(stdout, " %4d", year0);
-		// nyear++;
 	      }
 
 	    tsID++;
@@ -101,21 +95,18 @@ void *Showinfo(void *argument)
     }
   else if ( operatorID == SHOWMON )
     {
-      // int nmonth = 0;
       int tsID = 0;
       if ( ntsteps != 0 )
 	while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	  {
-	    vdate = taxisInqVdate(taxisID);
+	    int vdate = taxisInqVdate(taxisID);
 
 	    cdiDecodeDate(vdate, &year, &month, &day);
 	 
 	    if ( tsID == 0 || month0 != month )
 	      {
-		// if ( nmonth == 12 ) { nmonth = 0; fprintf(stdout, "\n"); }
 		month0 = month;
 		fprintf(stdout, " %2d", month0);
-		// nmonth++;
 	      }
 
 	    tsID++;
@@ -125,21 +116,18 @@ void *Showinfo(void *argument)
   else if ( operatorID == SHOWDATE )
     {
       char vdatestr[32];
-      // int ndate = 0;
       int tsID  = 0;
       if ( ntsteps != 0 )
 	while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	  {
-	    vdate = taxisInqVdate(taxisID);
+	    int vdate = taxisInqVdate(taxisID);
 	 
 	    date2str(vdate, vdatestr, sizeof(vdatestr));
 
 	    if ( tsID == 0 || date0 != vdate )
 	      {
-		// if ( ndate == 10 ) { ndate = 0; fprintf(stdout, "\n"); }
 		date0 = vdate;
 		fprintf(stdout, " %s", vdatestr);
-		// ndate++;
 	      }
 
 	    tsID++;
@@ -149,75 +137,73 @@ void *Showinfo(void *argument)
   else if ( operatorID == SHOWTIME )
     {
       char vtimestr[32];
-      // int nout = 0;
       int tsID = 0;
       if ( ntsteps != 0 )
 	while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	  {
-	    // if ( nout == 4 ) { nout = 0; fprintf(stdout, "\n"); }
-	    vtime = taxisInqVtime(taxisID);
+	    int vtime = taxisInqVtime(taxisID);
 
 	    time2str(vtime, vtimestr, sizeof(vtimestr));
 	    fprintf(stdout, " %s", vtimestr);
 
 	    tsID++;
-	    // nout++;
 	  }
       fprintf(stdout, "\n");
     }
   else if ( operatorID == SHOWTIMESTAMP )
     {
       char vdatetimestr[64];
-      // int nout = 0;
       int tsID = 0;
       if ( ntsteps != 0 )
 	while ( (nrecs = streamInqTimestep(streamID, tsID)) )
 	  {
-	    // if ( nout == 4 ) { nout = 0; fprintf(stdout, "\n"); }
-	    vdate = taxisInqVdate(taxisID);
-	    vtime = taxisInqVtime(taxisID);
+	    int vdate = taxisInqVdate(taxisID);
+	    int vtime = taxisInqVtime(taxisID);
 
 	    datetime2str(vdate, vtime, vdatetimestr, sizeof(vdatetimestr));
 	    fprintf(stdout, " %s", vdatetimestr);
 
 	    tsID++;
-            // nout++;
 	  }
       fprintf(stdout, "\n");
     }
   else if ( operatorID == SHOWCODE )
     {
-      // int nout = 0;
       for ( int varID = 0; varID < nvars; varID++ )
 	{
-	  // if ( nout == 20 ) { nout = 0; fprintf(stdout, "\n"); }
 	  fprintf(stdout, " %d", vlistInqVarCode(vlistID, varID));
-	  // nout++;
 	}
       fprintf(stdout, "\n");
     }
+  else if ( operatorID == SHOWGRID )  
+    {
+      fprintf(stdout, "# param nr | grid nr | z-axis nr:   /* Use in combination with operatores: griddes and zaxisdes */ \n");	  	  
+      for ( int varID = 0; varID < nvars; varID++ )
+	{
+	  int gridID  = vlistInqVarGrid(vlistID, varID);
+	  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+
+	  fprintf(stdout, "      %3d     %3d      %3d\n",
+                  vlistInqVarCode(vlistID, varID), vlistGridIndex(vlistID, gridID) + 1, vlistZaxisIndex(vlistID, zaxisID) + 1);
+	}
+    }    
   else if ( operatorID == SHOWUNIT )
     {
       char varunits[CDI_MAX_NAME];
-      //int nout = 0;
       for ( int varID = 0; varID < nvars; varID++ )
 	{
 	  varunits[0] = 0;
 	  vlistInqVarUnits(vlistID, varID, varunits);
-	  // if ( nout == 20 ) { nout = 0; fprintf(stdout, "\n"); }
           if ( strlen(varunits) ) fprintf(stdout, " %s", varunits);
-	  // nout++;
 	}
       fprintf(stdout, "\n");
     }
   else if ( operatorID == SHOWPARAM )
     {
-      int param;
       char paramstr[32];
-      
       for ( int varID = 0; varID < nvars; varID++ )
 	{
-	  param = vlistInqVarParam(vlistID, varID);
+	  int param = vlistInqVarParam(vlistID, varID);
 	  cdiParamToString(param, paramstr, sizeof(paramstr));
 
 	  fprintf(stdout, " %s", paramstr);
@@ -240,10 +226,7 @@ void *Showinfo(void *argument)
       for ( int varID = 0; varID < nvars; varID++ )
 	{
 	  vlistInqVarStdname(vlistID, varID, stdname);
-	  if ( stdname[0] != 0 )
-	    fprintf(stdout, " %s", stdname);
-	  else
-	    fprintf(stdout, " unknown");
+          fprintf(stdout, " %s", stdname[0] != 0 ? stdname : "unknown");
 	}
       fprintf(stdout, "\n");
     }
@@ -251,9 +234,9 @@ void *Showinfo(void *argument)
     {
       for ( int varID = 0; varID < nvars; varID++ )
 	{
-	  zaxisID = vlistInqVarZaxis(vlistID, varID);
-	  nlevs = zaxisInqSize(zaxisID);
-	  for ( levelID = 0; levelID < nlevs; levelID++ )
+	  int zaxisID = vlistInqVarZaxis(vlistID, varID);
+	  int nlevs = zaxisInqSize(zaxisID);
+	  for ( int levelID = 0; levelID < nlevs; levelID++ )
 	    fprintf(stdout, " %.9g", cdoZaxisInqLevel(zaxisID, levelID));
 	  fprintf(stdout, "\n");
 	}
@@ -263,9 +246,8 @@ void *Showinfo(void *argument)
       int nzaxis = vlistNzaxis(vlistID);
       for ( int index = 0; index < nzaxis; index++ )
 	{
-	  zaxisID = vlistZaxis(vlistID, index);
-
-	  ltype = zaxis2ltype(zaxisID);
+	  int zaxisID = vlistZaxis(vlistID, index);
+	  int ltype = zaxis2ltype(zaxisID);
 
 	  if ( ltype != -1 ) fprintf(stdout, " %d", ltype);
 	}
diff --git a/src/Sinfo.c b/src/Sinfo.c
index 48f4d38..37c4fcf 100644
--- a/src/Sinfo.c
+++ b/src/Sinfo.c
@@ -78,18 +78,10 @@ void limit_string_length(char* string, size_t maxlen)
 void *Sinfo(void *argument)
 {
   enum {func_generic, func_param, func_name, func_code};
-  int varID;
-  int gridsize = 0;
-  int gridID, zaxisID, code, tabnum, param;
-  int vdate, vtime;
-  int ntsteps;
-  int levelsize;
-  int tsteptype, taxisID;
   char tmpname[CDI_MAX_NAME];
   char varname[CDI_MAX_NAME];
   char paramstr[32];
   char vdatestr[32], vtimestr[32];
-  int datatype;
   char pstr[4];
 
   cdoInitialize(argument);
@@ -139,13 +131,13 @@ void *Sinfo(void *argument)
       reset_text_color(stdout);
       fprintf(stdout, "\n" );              
 
-      for ( varID = 0; varID < nvars; varID++ )
+      for ( int varID = 0; varID < nvars; varID++ )
 	{
-	  param   = vlistInqVarParam(vlistID, varID);
-	  code    = vlistInqVarCode(vlistID, varID);
-	  tabnum  = tableInqNum(vlistInqVarTable(vlistID, varID));
-	  gridID  = vlistInqVarGrid(vlistID, varID);
-	  zaxisID = vlistInqVarZaxis(vlistID, varID);
+	  int param   = vlistInqVarParam(vlistID, varID);
+	  int code    = vlistInqVarCode(vlistID, varID);
+	  int tabnum  = tableInqNum(vlistInqVarTable(vlistID, varID));
+	  int gridID  = vlistInqVarGrid(vlistID, varID);
+	  int zaxisID = vlistInqVarZaxis(vlistID, varID);
 
 	  set_text_color(stdout, BRIGHT, BLACK);
 	  fprintf(stdout, "%6d", varID+1);
@@ -170,7 +162,7 @@ void *Sinfo(void *argument)
 	  fprintf(stdout, "%-8s ", tmpname);
 
 	  /* tsteptype */
-	  tsteptype = vlistInqVarTsteptype(vlistID, varID);
+	  int tsteptype = vlistInqVarTsteptype(vlistID, varID);
 	  if      ( tsteptype == TSTEP_CONSTANT ) fprintf(stdout, "%-8s ", "constant");
 	  else if ( tsteptype == TSTEP_INSTANT  ) fprintf(stdout, "%-8s ", "instant");
 	  else if ( tsteptype == TSTEP_INSTANT2 ) fprintf(stdout, "%-8s ", "instant");
@@ -203,21 +195,21 @@ void *Sinfo(void *argument)
 	  reset_text_color(stdout);
 
 	  /* layer info */
-	  levelsize = zaxisInqSize(zaxisID);
+	  int levelsize = zaxisInqSize(zaxisID);
 	  set_text_color(stdout, RESET, GREEN);
 	  fprintf(stdout, "%6d ", levelsize);
 	  reset_text_color(stdout);
 	  fprintf(stdout, "%3d ", vlistZaxisIndex(vlistID, zaxisID) + 1);
 
 	  /* grid info */
-	  gridsize = gridInqSize(gridID);
+	  int gridsize = gridInqSize(gridID);
 	  set_text_color(stdout, RESET, GREEN);
 	  fprintf(stdout, "%9d ", gridsize);
 	  reset_text_color(stdout);
 	  fprintf(stdout, "%3d ", vlistGridIndex(vlistID, gridID) + 1);
 
 	  /* datatype */
-	  datatype = vlistInqVarDatatype(vlistID, varID);
+	  int datatype = vlistInqVarDatatype(vlistID, varID);
 	  datatype2str(datatype, pstr);
 
 	  set_text_color(stdout, RESET, BLUE);
@@ -252,7 +244,7 @@ void *Sinfo(void *argument)
 	    {
 	      char varextra[CDI_MAX_NAME];
 	      vlistInqVarExtra(vlistID, varID, varextra);
-	      fprintf(stdout, " : %s", varextra );              
+	      fprintf(stdout, " : %s", varextra);              
 	    }
 
 	  fprintf(stdout, "\n");
@@ -280,8 +272,8 @@ void *Sinfo(void *argument)
           printSubtypeInfo(vlistID);
         }
 
-      taxisID = vlistInqTaxis(vlistID);
-      ntsteps = vlistNtsteps(vlistID);
+      int taxisID = vlistInqTaxis(vlistID);
+      int ntsteps = vlistNtsteps(vlistID);
 
       if ( ntsteps != 0 )
 	{
@@ -297,8 +289,8 @@ void *Sinfo(void *argument)
 	    {
 	      if ( taxisInqType(taxisID) != TAXIS_ABSOLUTE )
 		{
-		  vdate = taxisInqRdate(taxisID);
-		  vtime = taxisInqRtime(taxisID);
+		  int vdate = taxisInqRdate(taxisID);
+		  int vtime = taxisInqRtime(taxisID);
 
 		  date2str(vdate, vdatestr, sizeof(vdatestr));
 		  time2str(vtime, vtimestr, sizeof(vtimestr));
diff --git a/src/Verifygrid.c b/src/Verifygrid.c
index 77b9ace..04abc2a 100644
--- a/src/Verifygrid.c
+++ b/src/Verifygrid.c
@@ -618,8 +618,18 @@ void verify_grid(int gridtype, int gridsize, int gridno, int ngrids, int ncorner
         
       int winding_number = winding_numbers_algorithm(cell_corners_plane_projection, actual_number_of_corners + 1, center_point_plane_projection);
 
+      // if ( winding_number == 0 ) printf("%d,", cell_no+1);
       if ( winding_number == 0 )
 	no_of_cells_with_center_points_out_of_bounds += 1;
+
+      if ( cdoVerbose && winding_number == 0 )
+        {
+          printf("cell_no %d: ", cell_no+1);
+          printf(" lon=%g lat=%g : ", grid_center_lon[cell_no], grid_center_lat[cell_no]);
+          for ( int corner_no = 0; corner_no < ncorner; corner_no++ )
+            printf(" %g/%g ", grid_corner_lon[cell_no * ncorner + corner_no], grid_corner_lat[cell_no * ncorner + corner_no]);
+          printf("\n");
+        }
     }
 
   int no_nonunique_cells = gridsize - no_unique_center_points;
diff --git a/src/Vertintml.c b/src/Vertintml.c
index 66e68e6..696d132 100644
--- a/src/Vertintml.c
+++ b/src/Vertintml.c
@@ -62,7 +62,6 @@ void change_hybrid_zaxis(int vlistID1, int vlistID2, int nvct, double *vct, int
 void *Vertintml(void *argument)
 {
   int mode;
-  enum {ECHAM_MODE, WMO_MODE};
   enum {func_pl, func_hl};
   enum {type_lin, type_log};
   int nrecs;
@@ -286,6 +285,14 @@ void *Vertintml(void *argument)
 	      mode = ECHAM_MODE;
 	      echam_gribcodes(&gribcodes);
 	    }
+      //  KNMI: HIRLAM model version 7.2 uses tableNum=1    (LAMH_D11*)
+      //  KNMI: HARMONIE model version 36 uses tableNum=1   (grib*)   (opreational NWP version)
+      //  KNMI: HARMONIE model version 38 uses tableNum=253 (grib,grib_md) and tableNum=1 (grib_sfx) (research version)
+	  else if ( tableNum == 1 || tableNum == 253 )
+	    {
+	      mode = HIRLAM_MODE;
+	      hirlam_harmonie_gribcodes(&gribcodes);
+	    }
 	  else
 	    mode = -1;
 	}
@@ -296,7 +303,11 @@ void *Vertintml(void *argument)
 	}
 
       if ( cdoVerbose )
-	cdoPrint("Mode = %d  Center = %d  Code = %d  Param = %s", mode, instNum, code, paramstr);
+        {
+          vlistInqVarName(vlistID1, varID, varname);
+	  cdoPrint("Mode = %d  Center = %d TableNum =%d Code = %d Param = %s Varname = %s varID = %d",
+                   mode, instNum, tableNum,  code, paramstr, varname, varID);
+        }
 
       if ( code <= 0 || code == 255 )
 	{
@@ -329,7 +340,7 @@ void *Vertintml(void *argument)
 	  else if ( code == gribcodes.lsp     && nlevel == 1      ) lnpsID    = varID;
 	  else if ( code == gribcodes.gheight && nlevel == nhlevf ) gheightID = varID;
 	}
-      else if ( mode == WMO_MODE )
+      else if ( mode == WMO_MODE || mode == HIRLAM_MODE )
 	{
 	  if      ( code == gribcodes.geopot  && nlevel == 1      ) sgeopotID = varID;
 	  else if ( code == gribcodes.geopot  && nlevel == nhlevf ) geopotID  = varID;
diff --git a/src/WindTrans.c b/src/WindTrans.c
new file mode 100644
index 0000000..3226c1f
--- /dev/null
+++ b/src/WindTrans.c
@@ -0,0 +1,1483 @@
+/*
+  This file is a extension of CDO.
+  Created by M. Koutek, 2012, KNMI (NL)
+
+  This file can eventually become a part of CDO.
+
+  CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2012 Uwe Schulzweida, Uwe.Schulzweida at zmaw.de
+  See COPYING file for copying and redistribution conditions.
+
+  This program 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; version 2 of the License.
+
+  This program 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.
+*/
+
+/*
+   This module contains the following operators:
+
+      WindTrans       uvDestag   : destagger U and/or V wind (in place)
+                      rotuvNorth : rotate grid-relative wind(u,v) to North_pole-relative
+*/
+
+#include <cdi.h>
+#include "cdo_int.h"
+#include "pstream.h"
+#include "grid.h"
+
+
+#define  MAXARG 10
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void streamGrbChangeModeUvRelativeToGrid(int mode);
+#if defined (__cplusplus)
+}
+#endif
+
+int UVDESTAG;
+int ROTUVNORTH;
+int ROTUVN;            // Fixed version of rotuvb operator !
+int PROJUVLATLON;
+
+
+// NOTE: Variable with codes (3[3,4],105,10) will get from CDO typically a name: "10u", resp. "10v"
+// Mostly u & v at level type 105 is not staggered, but test it to be sure..
+
+#define CheckVarIsU(varID,varname,code) {       \
+    VarIsU = 0;\
+    if ( lvar ) {\
+        if ( strcmp((char*)(varname), (char*)(chvars)[0]) == 0 ) VarIsU = 1;\
+    } else \
+        if ( code == chcodes[0] ) VarIsU = 1;\
+    }
+#define CheckVarIsV(varID,varname,code) {       \
+    VarIsV = 0;\
+    if ( lvar ) {\
+        if ( strcmp((char*)(varname), (char*)(chvars)[1]) == 0 ) VarIsV = 1;\
+    } else \
+        if ( code == chcodes[1] ) VarIsV = 1;\
+    }
+#define CheckUVisStaggered(varID1,varID2, zaxisID1, zaxisID2) { \
+    VarsUVareStaggered = 1;\
+    int gridID1tmp = vlistInqVarGrid(vlistID1, varID1);\
+    int gridID2tmp = vlistInqVarGrid(vlistID1, varID2);\
+    if (zaxisID1 != zaxisID2) VarsUVareStaggered = 0;\
+    else \
+    if (gridID1tmp==gridID2tmp) VarsUVareStaggered = 0;\
+    }
+
+
+static
+void destaggerUorV(double *fu, double *fuOut,
+                   int klev, int nlat, int nlon, int UorV, long offset)
+{
+  int lat0, lon0;
+  double u0,u1;
+  double u_dstg;
+  long  next;
+  /* This does de-staggering (-0.5; -0.5) */
+
+  long idx = offset;
+  if (UorV==0)
+    {
+      next = -1;    // U-wind
+      lat0=0; lon0 = 1;
+    }
+  else
+    {
+      next = -nlon; // V-wind: length of the row (2d array)
+      lat0=1; lon0 = 0;
+    }
+
+  if ( cdoDebugExt>=20 )
+    cdoPrint("destaggerUorV(): (nlon=%d, nlat=%d);               [lat0=%d, lon0=%d, next=%d];    (default order destaggering)", nlon,nlat, lat0,lon0,next);
+
+  for ( int lev = 0; lev < klev; lev++ )
+    {
+      if (lat0)  // the first row we let as it is
+        for ( int lon = 0; lon < nlon; lon++ )
+          {
+            u0 = fu[idx];
+            fuOut[idx] = u0;
+            idx++;
+          }
+      for ( int lat = lat0; lat < nlat; lat++ )
+        {
+          if (lon0)// the first column we let as it is
+            {
+              u0 = fu[idx];
+              fuOut[idx] = u0;
+              idx++;
+            }
+          for ( int lon = lon0; lon < nlon; lon++ )
+            {
+              u0 = fu[idx];
+              u1 = fu[idx+next];
+              u_dstg = 0.5*(u0+u1);
+              fuOut[idx] = u_dstg;
+              idx++;
+            }
+        }
+    }
+}
+
+static
+void destaggerUorV_positiveOrder(double *fu, double *fuOut,
+                   int klev, int nlat, int nlon, int UorV, long offset)
+{
+  int latE, lonE;
+  double u0,u1;
+  double u_dstg;
+  long next;
+  /* This does de-staggering (+0.5; +0.5) */
+
+  long idx=offset;
+  if (UorV==0) // U-wind: length of the row (2d array)
+    {
+      next = nlon;
+      latE = nlat-1; lonE = nlon;
+    }
+  else        // V-wind:
+    {
+      next = 1;
+      latE = nlat; lonE = nlon-1;
+    }
+  
+  if ( cdoDebugExt>=20 )
+    cdoPrint("destaggerUorV(): (nlon=%d, nlat=%d);               [latE=%d, lonE=%d, next=%d];    (positive order destaggering)", nlon,nlat, latE,lonE,next);
+
+  for ( int lev = 0; lev < klev; lev++ )
+    {
+      for ( int lat = 0; lat < latE; lat++ )
+        {
+          for ( int lon = 0; lon < lonE; lon++ )
+            {
+              u0 = fu[idx];
+              u1 = fu[idx+next];
+              u_dstg = 0.5*(u0+u1);
+              fuOut[idx] = u_dstg;
+              idx++;
+            }
+          if (lonE<nlon)   // the last column we let as it is
+            {
+              u0 = fu[idx];
+              fuOut[idx] = u0;
+              idx++;
+            }
+        }
+      if (latE<nlat)   // the last row we let as it is
+        for ( int lon = 0; lon < nlon; lon++ )
+          {
+            u0 = fu[idx];
+            fuOut[idx] = u0;
+            idx++;
+          }
+    }
+}
+
+static
+void *DestaggerUV()
+{
+  int nrecs;
+  int varID, levelID;
+  int varID1 = CDI_UNDEFID, varID2 = CDI_UNDEFID;
+  int zaxisID1 = CDI_UNDEFID, zaxisID2 = CDI_UNDEFID;
+  int varID1stg = CDI_UNDEFID, varID2stg = CDI_UNDEFID;
+  int gridsize;
+  int chcodes[MAXARG];
+  char *chvars[MAXARG];
+  char varname[CDI_MAX_NAME];
+  double destagGridOffsets[MAXARG];
+  int gridID1 = CDI_UNDEFID, gridID2 = CDI_UNDEFID;
+  int gridID0 = CDI_UNDEFID;
+  int gridID;
+  bool lcopy = false;
+  int UorV;
+  int nlon = 0, nlat = 0;
+  double *ivar = NULL, *ovar = NULL;
+  double dxU = 0, dyU = 0, dxV = 0, dyV = 0;
+
+  //Note: Already initialized by the caller! Don't call again: cdoInitialize(argument);
+
+  operatorInputArg("Pair of u and v in the staggered system:\n\
+    Usage: uvDestag,u,v -or- uvDestag,33,34 -or- uvDestag,u,v,-0.5,-0.5 -or- uvDestag,33,34,-0.5,-0.5\n \
+    Destaggered grid offsets <,-/+0.5,-/+0.5> are optional.\n           \
+    If file contains grid with temperature (name='t' or code=11) then grid_temp will be used for destaggered wind.");
+
+  if ( cdoDebugExt ) cdoPrint("UVDESTAG (destaggering) requested)..");
+
+  int nch = operatorArgc();
+  if ( nch<2 ) cdoAbort("Number of input arguments < 2; At least 2 arguments needed: uvDestag,33,34<,-0.5,-0.5> optional");
+  if ( nch>=MAXARG ) cdoAbort("Number of input arguments >= %d", MAXARG);
+
+  bool lvar = false;
+  if ( isdigit(*operatorArgv()[0]) )
+    {
+      lvar = false;  // We have a list of codes
+      for ( int i = 0; i < 2; i++ ) chcodes[i] = parameter2int(operatorArgv()[i]);
+    }
+  else
+    {
+      lvar = true;  // We have a list of variables
+      for ( int i = 0; i < 2; i++ ) chvars[i] = operatorArgv()[i];
+    }
+
+  destagGridOffsets[0] = -0.5;
+  destagGridOffsets[1] = -0.5;
+
+  if ( nch > 2 )
+    {
+      for ( int i = 2; i < (2+2); i++ )
+        destagGridOffsets[i-2] = parameter2double(operatorArgv()[i]);
+    }
+
+  if ( cdoDebugExt ) cdoPrint("destagGridOffsets = (%01.1f,%01.1f)", destagGridOffsets[0],destagGridOffsets[1]);
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
+
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  // Find the first occurance of staggered U and V variables (for example codes 33,34).
+  // We assume that one (grib-)file contains only 1 sort of horizontal grids and at most 2 staggered grids.
+  /*
+    [Hirlam/hip_work] >cdo sinfo LAMH_D11_201302150000_00000_GB_only_UV
+    File format: GRIB
+    -1 : Institut Source   Param       Ttype   Dtype  Gridsize Num  Levels Num
+     1 : KNMI     unknown  11.1        instant  P11    399300   1      19   1
+     2 : KNMI     unknown  33.1        instant  P13    399300   1       6   2  ** non-staggered U  (leveltype=105)
+     3 : KNMI     unknown  34.1        instant  P12    399300   1       6   2  ** non-staggered V  (leveltype=105)
+     4 : KNMI     unknown  33.1        instant  P14    399300   2      60   3  ** STAGGERED U  (leveltype=109)
+     5 : KNMI     unknown  34.1        instant  P14    399300   3      60   3  ** STAGGERED V  (leveltype=109)
+     6 : KNMI     unknown  11.1        instant  P11    399300   1      60   3
+     7 : KNMI     unknown  11.1        instant  P10    399300   1       1   4
+     8 : KNMI     unknown  11.1        instant  P11    399300   1      11   5
+     9 : KNMI     unknown  33.1        instant  P14    399300   2      11   5  ** STAGGERED U  (leveltype=100)
+    10 : KNMI     unknown  34.1        instant  P14    399300   3      11   5  ** STAGGERED V  (leveltype=100)
+    Horizontal grids :
+     1 : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.2  last = 42.3  inc = 0.1  degrees
+                        rlat      : first = -30.8  last = 24.1  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+     2 : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.15  last = 42.35  inc = 0.1  degrees
+                        rlat      : first = -30.8  last = 24.1  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+     3 : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.2  last = 42.3  inc = 0.1  degrees
+                        rlat      : first = -30.75  last = 24.15  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+    Vertical grids :
+     1 : height                 m : 0 2 801 802 803 804 805 901 902 903 904 905 951
+                                    952 953 954 955 998 999
+     2 : height                 m : 10 801 802 803 804 805
+     3 : hybrid             level : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+                                    20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
+                                    36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
+                                    52 53 54 55 56 57 58 59 60
+     4 : meansea            level : 0
+     5 : pressure              Pa : 5000 10000 20000 25000 30000 40000 50000 70000
+                                    85000 92500 100000
+  */
+  int VarIsU,VarIsV;
+  int VarsUVareStaggered;
+
+  // Search for staggered u and v wind:
+  int nvars = vlistNvars(vlistID1);
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      int param = vlistInqVarParam(vlistID1, varID);
+      int pnum, pcat, pdis;
+      cdiDecodeParam(param, &pnum, &pcat, &pdis);
+      int code = pnum;
+      int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+      int ltype   = zaxis2ltype(zaxisID);
+      int nlevs   = zaxisInqSize(zaxisID);
+      vlistInqVarName(vlistID1, varID, varname);
+      int gridIDx = vlistInqVarGrid(vlistID1, varID);
+      if ( cdoDebugExt>=20 )
+        cdoPrint("Var.id [%4d] with grib code:3%d and has name: %6s; level type: %3d; number of levels: %3d; gridID: %d; zaxisID: %d",
+                 varID, code, varname, ltype, nlevs, gridIDx, zaxisID);
+
+      CheckVarIsU(varID, varname, code);
+      CheckVarIsV(varID, varname, code);
+      if      (VarIsU) { varID1 = varID; zaxisID1 = zaxisID; }
+      else if (VarIsV) { varID2 = varID; zaxisID2 = zaxisID; }
+
+      if ( (varID1stg == -1) && (varID2stg == -1) )
+        if ( (varID1 != -1) && (varID2 != -1) )
+          {
+            CheckUVisStaggered(varID1,varID2, zaxisID1, zaxisID2);
+            if ( VarsUVareStaggered )
+              {
+                gridID1 = vlistInqVarGrid(vlistID1, varID1);
+                gridID2 = vlistInqVarGrid(vlistID1, varID2);
+                if ( cdoDebugExt )
+                  cdoPrint("Found STAGGERED U & V: varID1=%d (gridID1=%d), varID2=%d (gridID2=%d)",varID1, gridID2, varID2, gridID1);
+                varID1stg = varID1;
+                varID2stg = varID2;
+              }
+          }
+      // search for a reference (non-staggered) grid
+      // We take temperature for example as the new (horizontal) grid for de-staggered uv
+      // If there will be no temperature field we will define grid the grid
+      if ( lvar )  // We have a list of variables
+        {
+          if ( strcmp(varname, "t") == 0 ) gridID0 = vlistInqVarGrid(vlistID1, varID);
+        }
+      else
+        {
+          if ( code == 11 ) gridID0 = vlistInqVarGrid(vlistID1, varID);
+        }
+    } // end of for ( varID = 0; varID < nvars; ..
+
+  if (gridID0>=0)
+    if ( cdoDebugExt ) cdoPrint("Found DESTAGGERED grid for U, V: gridID0=%d",gridID0);
+
+  if ( (varID1stg == -1) && (varID2stg == -1) )
+    {
+      cdoPrint("NOTE: We did not find any staggered U,V wind components. Performing file-copy.");
+      lcopy = true;
+      gridID0 = gridID1;
+    }
+
+  int ngrids = vlistNgrids(vlistID1);
+
+  double xincU = gridInqXinc(gridID1);
+  double yincU = gridInqXinc(gridID1);
+  double xincV = gridInqXinc(gridID2);
+  double yincV = gridInqXinc(gridID2);
+
+  if ( !lcopy )
+    {
+      if ( gridInqXsize(gridID1) != gridInqXsize(gridID2) )  cdoAbort("Xsize(gridID1) != Xsize(gridID2)");
+      if ( gridInqYsize(gridID1) != gridInqYsize(gridID2) )  cdoAbort("Ysize(gridID1) != Ysize(gridID2)");
+      
+      nlon = gridInqXsize(gridID1);
+      nlat = gridInqYsize(gridID1);
+
+      if ( ! (gridInqType(gridID1) == GRID_PROJECTION && gridInqProjType(gridID1) == CDI_PROJ_RLL &&
+              gridInqType(gridID2) == GRID_PROJECTION && gridInqProjType(gridID2) == CDI_PROJ_RLL) )
+        {
+          cdoPrint("U - wind: Grid nr. %d is gridtype: %d (%s)", gridID1, gridInqType(gridID1), gridNamePtr(gridInqType(gridID1)));
+          cdoPrint("V - wind: Grid nr. %d is gridtype: %d (%s)", gridID2, gridInqType(gridID2), gridNamePtr(gridInqType(gridID2)));
+          cdoAbort("Destaggering supports only grid type = 'lonlat' (GRID_LONLAT).");
+        }
+
+      /* define output grid */
+      if ( gridID0 == -1 )
+        {
+          if ( cdoDebugExt )
+            cdoPrint("Calling define_destagered_grid( destagGridOffsets = (%01.1f,%01.1f) )", destagGridOffsets[0], destagGridOffsets[1]);
+          gridID0 = cdo_define_destagered_grid(gridID1, gridID2, destagGridOffsets);
+        }
+
+      if ( gridID0 == -1 ) cdoAbort("Cannot define DESTAGGERED grid for U, V.");
+
+      if ( cdoDebugExt>=10 ) cdo_print_grid(gridID0, 1);
+
+      double xfirst_R = gridInqXval(gridID0,0); // reference grid for non-staggered fields (default: search for temperature; otherwise: create a new grid)
+      double yfirst_R = gridInqYval(gridID0,0);
+      double xfirst_U = gridInqXval(gridID1,0); // grid of u-wind
+      double yfirst_U = gridInqYval(gridID1,0);
+      double xfirst_V = gridInqXval(gridID2,0); // grid of v-wind
+      double yfirst_V = gridInqYval(gridID2,0);
+
+      dxU = -xfirst_U + xfirst_R;
+      dyU = -yfirst_U + yfirst_R;
+      dxV = -xfirst_V + xfirst_R;
+      dyV = -yfirst_V + yfirst_R;
+
+      if ( cdoDebugExt )
+        {
+          cdoPrint("Grid info: (xfirst_R = %3.2f; yfirst_R = %3.2f); (xfirst_U = %3.2f; yfirst_U = %3.2f); (xfirst_V = %3.2f; yfirst_V = %3.2f);",
+                   xfirst_R,yfirst_R,xfirst_U,yfirst_U,xfirst_V,yfirst_V);
+          cdoPrint("Grid info: (dxU; dyU) = (%3.2f; %3.2f); (dxV; dyV) = (%3.2f; %3.2f) ", dxU, dyU, dxV, dyV);
+          cdoPrint("Grid info: nlon=%d, nlat=%d ", nlon, nlat);
+        }
+      if ( cdoDebugExt )
+        {
+          if (dxU<0)
+            cdoPrint("About to perform destaggering (U-wind): (%3.2f; %3.2f) - default order ", dxU, dyV);
+          else
+            cdoPrint("About to perform destaggering (U-wind): (%3.2f; %3.2f) - positive order ", dxU, dyV);
+        }
+
+      if ( cdoDebugExt )
+        {
+          if (dyV<0)
+            cdoPrint("About to perform destaggering (V-wind): (%3.2f; %3.2f) - default order ", dxU,dyV);
+          else
+            cdoPrint("About to perform destaggering (V-wind): (%3.2f; %3.2f) - positive order ", dxU,dyV);
+        }
+
+      for ( int index = 0; index < ngrids; index++ )
+        {
+          gridID = vlistGrid(vlistID1, index);
+          if ( cdoDebugExt>=10 ) cdoPrint("Grid nr. %d is gridtype: %d (%s)", index, gridInqType(gridID), gridNamePtr(gridInqType(gridID)));
+        }
+
+      if (gridID0 == -1)
+        {
+          if ( cdoDebugExt ) cdoPrint("Last trial to find a reference grid for destaggered wind.");
+          for ( varID = 0; varID < nvars; varID++ )
+            {
+              gridID = vlistInqVarGrid(vlistID1, varID);
+              if ( cdoDebugExt ) cdoPrint("Var.id %d has grid nr:%d", varID,  gridID);
+              if ( (varID!=varID1stg) && (varID!=varID2stg) )
+                {
+                  // this will the new (horizontal) grid for de-staggered
+                  gridID0 = vlistInqVarGrid(vlistID1, varID);
+                }
+            }
+        }
+      if ( gridID0 == -1 ) cdoAbort("Referencial horizontal grid not found!");
+
+      gridsize = vlistGridsizeMax(vlistID1);
+
+      if ( gridInqSize(gridID2)!= gridInqSize(gridID1) )
+        cdoAbort("gridSize of U-wind != gridSize of V-wind!  This should not happen!");
+
+      if ( cdoDebugExt ) cdoPrint("Allocating memory for maximum gridsize (for input) = %ld [%4.3f MB]",gridsize, gridsize*sizeof(double)/(1024.0*1024));
+      ivar = (double *) Malloc(gridsize*sizeof(double));  // storage for other fields than
+
+      gridsize = gridInqSize(gridID1);  // actual size of U-wind should be same as V-wind
+      if ( cdoDebugExt )
+        cdoPrint("Allocating memory for gridsize (destaggered output)= %ld; nlon=%d, nlat=%d",gridsize,nlon,nlat );
+      ovar = (double *) Malloc(gridsize*sizeof(double));
+    } // end of  if (!lcopy)
+
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+  if ( varID1stg != CDI_UNDEFID && varID2stg != CDI_UNDEFID )
+    {
+      vlistChangeVarGrid(vlistID2, varID1stg, gridID0);   // set the variable onto the non-staggered grid
+      vlistChangeVarGrid(vlistID2, varID2stg, gridID0);   // set the variable onto the non-staggered grid
+    }
+
+  streamDefVlist(streamID2, vlistID2);  // from this point the stream is using a different vlistID !!!!!
+  vlistID2 = streamInqVlist(streamID2); // refresh it
+  
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+      streamDefTimestep(streamID2, tsID);
+
+      if ( !lcopy && cdoDebugExt )
+        {
+          cdoPrint("Processing timestep: %d",tsID);
+          cdoPrint("Starting destaggering. Total records to be processed: %05d", nrecs);
+        }
+
+      for ( int recID = 0; recID < nrecs; recID++ )
+        {
+          streamInqRecord(streamID1, &varID, &levelID);
+          int param = vlistInqVarParam(vlistID1, varID);
+          int pnum, pcat, pdis;
+          cdiDecodeParam(param, &pnum, &pcat, &pdis);
+          int code = pnum;
+          int zaxisID = vlistInqVarZaxis(vlistID1, varID);
+          int ltype = zaxis2ltype(zaxisID);
+          int level = (int) zaxisInqLevel(zaxisID, levelID);
+
+          if ( !lcopy )
+            {
+              VarIsU = (varID == varID1stg);
+              VarIsV = (varID == varID2stg);
+
+              UorV = -1;            // -1: not U, neither V
+              if      (VarIsU) UorV = 0; // 0: U-wind; 1: V-wind
+              else if (VarIsV) UorV = 1;
+
+              if (UorV>=0)
+                {
+                  gridID = vlistInqVarGrid(vlistID1, varID);
+                  if (UorV==0)
+                    {
+                      if (gridID==gridID1) // Has this variable the staggered grid?
+                        {
+                          if ( cdoDebugExt>=10 )
+                            cdoPrint("Destaggering U-wind record: %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d); GridID %d => %d  *** <===",
+                                     recID, tsID, varID, code, ltype, level, levelID, vlistInqVarGrid(vlistID1, varID), vlistInqVarGrid(vlistID2, varID));
+                        }
+                      else UorV=-1;  // this U is not staggered, just copy the record..
+                    }
+                  if (UorV==1)
+                    {
+                      if (gridID==gridID2) // Has this variable the staggered grid?
+                        {
+                          if ( cdoDebugExt>=10 )
+                            cdoPrint("Destaggering V-wind record: %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d); GridID %d => %d  *** <===",
+                                     recID, tsID, varID, code, ltype, level, levelID, vlistInqVarGrid(vlistID1, varID), vlistInqVarGrid(vlistID2, varID));
+                        }
+                      else UorV=-1;  // this V is not staggered, just copy the record..
+                    }
+                } // end of: if (UorV>=0)
+
+              if (UorV>=0)  // re-check again since it could mean that current record with U or V is not staggered
+                {
+                  int nmiss;
+                  streamReadRecord(streamID1, ivar, &nmiss);
+                  // read the original record with staggered u or v
+                  gridsize = gridInqSize(gridID1);
+
+                  //void destaggerUorV(double *fu, double *fuOut,
+                  //                   int klev, int nlat, int nlon, int UorV, long int offset);
+                  // We handle one level at the time; klev=1;offset=0.
+                  if ( (dxU<0.0) && (dyV<0.0))
+                    // UorV = 0: U-wind; 1: V-wind
+                    destaggerUorV(ivar, ovar,1, nlat, nlon, UorV, 0);
+                  else if ( (dyU>0.0) && (dxV>0.0))
+                    // UorV = 0: U-wind; 1: V-wind
+                    destaggerUorV_positiveOrder(ivar, ovar,1, nlat, nlon, UorV, 0);
+                  else
+                    cdoAbort("Unsupported destaggering grid offset: (dxU; dyU) = (%3.2f; %3.2f); (dxV; dyV) = (%3.2f; %3.2f) where: xincU=%3.2f, yincU=%3.2f, xincV=%3.2f, yincV=%3.2f",
+                             dxU,dyU, dxV,dyV, xincU, yincU, xincV, yincV);
+
+                  // Typical Hirlam LAMH_D11 situation with destaggering on (-0.5,-0.5)
+                  // cdo uvDestag: Grid info: (xfirst_R = -30.20; yfirst_R = -30.80); (xfirst_U = -30.15; yfirst_U = -30.80); (xfirst_V = -30.20; yfirst_V = -30.75);
+                  // cdo uvDestag: Grid info: (dxU; dyU) = (-0.05; 0.00); (dxV; dyV) = (0.00; -0.05)
+
+                  // Less typical would be to choose destaggering on (+0.5,+0.5)
+                  // cdo uvDestag: Grid info: (xfirst_R = -30.15; yfirst_R = -30.75); (xfirst_U = -30.15; yfirst_U = -30.80); (xfirst_V = -30.20; yfirst_V = -30.75);
+                  // cdo uvDestag: Grid info: (dxU; dyU) = (0.00; 0.05); (dxV; dyV) = (0.05; 0.00)
+                  if ( cdoDebugExt>=20 ) cdoPrint("Setting GRID id from: %d => to: %d", vlistInqVarGrid(vlistID1, varID), vlistInqVarGrid(vlistID2, varID) );
+
+                  streamDefRecord(streamID2, varID, levelID);
+                  streamWriteRecord(streamID2, ovar, nmiss);
+                }
+              else
+                {   // copy the record to the output unchanged...
+                  streamDefRecord(streamID2, varID, levelID);
+                  if ( cdoDebugExt>=20 )
+                    cdoPrint("Stream-copy data record:    %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d)",
+                             recID, tsID, varID, code, ltype, level, levelID);
+                  streamCopyRecord(streamID2, streamID1);
+                }
+            }  // end of: if (!lcopy)
+          else
+            {   // copy the record to the output unchanged...
+              streamDefRecord(streamID2, varID, levelID);
+              if ( cdoDebugExt>=20 )
+                cdoPrint("Stream-copy data record:    %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d)",
+                         recID, tsID, varID, code, ltype, level, levelID);
+              streamCopyRecord(streamID2, streamID1);
+            }
+
+        } // end of for ( recID = ...
+
+        tsID++;
+    } // end of while ( (nrecs ...
+
+  streamClose(streamID2);
+  streamClose(streamID1);
+
+  if ( ivar ) Free(ivar);
+  if ( ovar ) Free(ovar);
+
+  cdoFinish();
+
+  return 0;
+}
+
+static
+void rot_uv_north(int gridID, double *us, double *vs)
+{
+  // Function transforms grid-relative UV into north-pole relative UV in the (spherical) lat-lon coordinate space.
+  // Input:  u,v : grid relative (u,v); NOT staggered
+  //
+  // This function needs that the gridpoint coordinates have been transformed from modelspace
+  // into LatLon space using function gridToCurvilinear().
+  //
+  // xvals[], yvals[] contains the Lon-Lat coordinates.
+
+  if ( gridInqType(gridID) != GRID_CURVILINEAR )
+    cdoAbort("%s(gridname=%s) grid must be GRID_CURVILINEAR!", __func__, gridNamePtr(gridInqType(gridID)));
+  // this should never happen
+
+  static double *rotationMatrixArray = NULL;
+  double lon_pnt0, lat_pnt0;
+  double lon_pntEast = 0, lat_pntEast = 0;
+  double lon_pntNorth, lat_pntNorth;
+  double dLatEast = 0, dLonEast = 0;
+  double dLatNorth, dLonNorth;
+  double xpntEastSph,ypntEastSph, zpntEastSph = 0;
+  double xpntNorthSph, ypntNorthSph, zpntNorthSph;
+  double xpntNorthSphRot, ypntNorthSphRot, zpntNorthSphRot;
+  double xpnt0Sph, ypnt0Sph, zpnt0Sph;
+  double xnormSph, ynormSph, znormSph;
+  double xncross,  yncross,  zncross;
+  double vecAngle;
+  long idx, idx4;
+  int i,j;
+  double VJaa,VJab,VJba,VJbb;
+  double u,v;
+  double magnitude, newMagnitude;
+  double uu;
+  double vv;
+
+  // The following "correction for the grid-step direction" from funtion project_uv_latlon()
+  // cannot be used here!
+  // This cannot be done in the geographic lon/lan (on the globe).
+  //int signLon=( (xvals[1] - xvals[0]) < 0 )?-1:1;
+  //int signLat=( (yvals[1] - yvals[0]) < 0 )?-1:1;
+  /*
+      Tested for scanning mode 64 LAMH_D11:
+      -------------------------------------
+      iScansNegatively = 0;
+      jScansPositively = 1;
+      jPointsAreConsecutive = 0;
+      #-READ ONLY- alternativeRowScanning = 0;
+      jDirectionIncrementInDegrees = 0.1;
+      iDirectionIncrementInDegrees = 0.1;
+
+      !!! When scanning mode 00 the lons & lats arrays: xvals[idx] & yvals[idx]; are upside-down !!!
+
+        iScansNegatively = 0;
+        jScansPositively = 0;
+        jPointsAreConsecutive = 0;
+        #-READ ONLY- alternativeRowScanning = 0;
+        jDirectionIncrementInDegrees = 0.1;  // this should be -0.1 ??
+        iDirectionIncrementInDegrees = 0.1;
+  */
+
+  int nx = gridInqXsize(gridID);
+  int ny = gridInqYsize(gridID);
+    
+  double *xvals = (double *) Malloc(nx*ny*sizeof(double));
+  double *yvals = (double *) Malloc(nx*ny*sizeof(double));
+  gridInqXvals(gridID, xvals);
+  gridInqYvals(gridID, yvals);
+
+  int scanningMode = gridInqScanningMode(gridID);
+  bool jScansPositively = (scanningMode == 64);
+  if (scanningMode==64)
+    {
+      if ( cdoDebugExt>1 )
+        cdoPrint("NOTICE: Processing data with scanning mode(%d); gridID=%d", scanningMode, gridID);
+    }
+  else if (scanningMode==0)
+    {
+      if ( cdoDebugExt>1 )
+        cdoPrint("NOTICE: Processing data with scanning mode(%d); gridID=%d", scanningMode, gridID);
+    }
+  else
+    {
+      cdoAbort("\n***\n***\n WARNING! Unsupported data scanning mode(%d); gridID=%d; For this operation we support only: 64,00 \n"
+               "RESULT will be probably incorrect!\n***\n***", scanningMode, gridID);
+    }
+
+
+  if (cdoDebugExt)
+    cdoPrint("%s(gridname=%s) .. processing grid with UV [nx*ny] (%d * %d)", __func__, gridNamePtr(gridInqType(gridID)), nx, ny );
+
+  if (gridInqSize(gridID) != (nx*ny) )
+    cdoAbort("Incorrect gridsize (%d) != nx*ny (%d * %d)", gridInqSize(gridID), nx, ny);
+  // this should never happen
+
+#define OPTrotuvNorth 1   // ACTIVATE SPEED - OPTIMIZATION
+
+#define radians(aDeg) (DEG2RAD*aDeg)
+#define NormVector(vec0,vec1,vec2) {\
+    double vecLen = sqrt(vec0*vec0 + vec1*vec1 + vec2*vec2);\
+    vec0 = vec0/vecLen; vec1 = vec1/vecLen; vec2 = vec2/vecLen; }
+
+#define CrossProd(vecx0,vecx1,vecx2, vecy0,vecy1,vecy2, vecz0,vecz1,vecz2) {\
+    vecz0 = vecx1*vecy2 - vecy1*vecx2;\
+    vecz1 = vecx2*vecy0 - vecy2*vecx0;\
+    vecz2 = vecx0*vecy1 - vecy0*vecx1; }
+
+  if ( rotationMatrixArray == NULL )
+    {
+      if ( cdoDebugExt>0 )
+        cdoPrint("About to compute rotationMatrixArray for the whole grid [%d x %d]", nx,ny);
+
+      rotationMatrixArray = (double *) Malloc(4*nx*ny*sizeof(double));
+      for ( j = 0; j < ny; j++ )
+        for ( i = 0; i < nx; i++ )
+          {
+            idx = j*nx+i;
+            lon_pnt0 = xvals[idx];
+            lat_pnt0 = yvals[idx];
+#ifndef OPTrotuvNorth
+            // For speed - optimization not used and not needed. Kept only for clarity.
+            if ((i+1)<nx)
+              {   lon_pntEast = xvals[idx+1];  // longitude of grid point towards east
+                lat_pntEast = yvals[idx+1]; }//  latitude of grid point towards east
+            else
+              {   lon_pntEast = lon_pnt0 + 1.0*(lon_pnt0 - xvals[idx-1]); // at the grid border define extended gridpoint
+                lat_pntEast = lat_pnt0 + 1.0*(lat_pnt0 - yvals[idx-1]); }
+#endif //#ifdef OPTrotuvNorth
+            if ((j+1)<ny)
+              {   lon_pntNorth = xvals[idx+nx];  // longitude of grid point towards north
+                lat_pntNorth = yvals[idx+nx]; }//  latitude of grid point towards north
+            else
+              {   lon_pntNorth = lon_pnt0 + 1.0*(lon_pnt0 - xvals[idx-nx]); // at the grid border define extended gridpoint
+                lat_pntNorth = lat_pnt0 + 1.0*(lat_pnt0 - yvals[idx-nx]); }
+
+            // (lon_pntNorth, lat_pntNorth)
+            //     ^
+            //     |       (lon_pntCenter, lat_pntCenter)   center of the cell-diagonal
+            //     |
+            // (lon_pnt0,lat_pnt0) ----> (lon_pntEast,lat_pntEast)
+
+            //lon_pntCenter = 0.5*(lon_pntNorth + lon_pntEast);
+            //lat_pntCenter = 0.5*(lat_pntNorth + lat_pntEast);
+            //lon_pnt0 -= lon_pntCenter; lon_pntEast -= lon_pntCenter; lon_pntNorth -= lon_pntCenter;
+            //lat_pnt0 -= lat_pntCenter; lat_pntEast -= lat_pntCenter; lat_pntNorth -= lat_pntCenter;
+
+            // This is the local coordinate system of a grid cell where we have (u,v) at location (xpnt0,ypnt0).
+
+            // The local coordinate system is now centered around (lon_pnt0,lat_pnt0)
+            // The vector towards north pole (UP-VECTOR) at this location will be (0,1,0)
+            // The tangent plane at this location is XY wil a normal (0, 0, 1)
+
+            // Nummerical approach using projection onto a unit sphere
+            lon_pnt0 = radians(lon_pnt0); lat_pnt0 = radians(lat_pnt0);
+            xpnt0Sph = cos(lat_pnt0) * cos(lon_pnt0);
+            ypnt0Sph = cos(lat_pnt0) * sin(lon_pnt0);   // # Get [lon_pnt0,lat_pnt0] on the unit sphere.
+            zpnt0Sph = sin(lat_pnt0);                   // # Only XY plane is needed.
+            dLonNorth = radians(lon_pntNorth); dLatNorth = radians(lat_pntNorth);
+            xpntNorthSph = cos(dLatNorth) * cos(dLonNorth);
+            ypntNorthSph = cos(dLatNorth) * sin(dLonNorth); // # Get [dLonNorth,dLatNorth] on the unit sphere.
+            zpntNorthSph = sin(dLatNorth);                   //# Only XY plane is needed.
+            xpntNorthSph-= xpnt0Sph, ypntNorthSph-= ypnt0Sph; zpntNorthSph-= zpnt0Sph;
+            NormVector( xpntNorthSph, ypntNorthSph, zpntNorthSph );  // vecy
+
+
+#ifndef OPTrotuvNorth
+            // For speed - optimization not used and not needed. Kept only for clarity.
+            dLonEast = radians(lon_pntEast); dLatEast = radians(lat_pntEast);
+            xpntEastSph = cos(dLatEast) * cos(dLonEast);
+            ypntEastSph = cos(dLatEast) * sin(dLonEast);  // # Get [dLonEast,dLatEast] on the unit sphere.
+            zpntEastSph = sin(dLatEast);                  // # Only XY plane is needed.
+            xpntEastSph -= xpnt0Sph; ypntEastSph -= ypnt0Sph; zpntEastSph -= zpnt0Sph;  // make vectors from points
+            NormVector( xpntEastSph,  ypntEastSph,  zpntEastSph );  // vecx
+            //vecz = CrossProd(vecx,vecy)
+            CrossProd( xpntEastSph,  ypntEastSph,  zpntEastSph,  xpntNorthSph, ypntNorthSph, zpntNorthSph, \
+                       xnormSph, ynormSph, znormSph);  // vec z
+#else
+            xnormSph = xpnt0Sph; ynormSph = ypnt0Sph; znormSph = zpnt0Sph;
+            NormVector(xnormSph, ynormSph, znormSph);  // vec z ... normal vector to the sphere at pnt0 (lon_pnt0,lat_pnt0)
+#endif //#ifdef OPTrotuvNorth
+
+            //# vecUP = (0.0,0.0,1.0) .. up-vector in a global coordinate system
+            //#   ^^ up-vector & vector-towards-north-pole & shere-normal-vector belong to ONE plane
+            //#      that crosses north pole and point pnt0 (lon_pnt0,lat_pnt0)
+            //# Project vecUP onto plane XY, where plane-normal is vecz
+            //# vecnProjXY = vecUP - D*vecz;   D= a*x1+b*y1+c*z1;  vecz=(a,b,c); vecUP = (x1,y1,z1)=(0,0,1)
+            //#                               D= vecz[2]*1;
+            //# vecyRot = NormVector( (0.0 - vecz[2]*vecz[0],0.0  - vecz[2]*vecz[1], 1.0  - vecz[2]*vecz[2]) )
+
+            //double Dist =  xnormSph * 0.0 +  ynormSph * 0.0 + znormSph * 1.0; // Left out for optimization
+            xpntNorthSphRot =     - znormSph*xnormSph;  // xpntNorthSphRot = 0.0 - Dist*xnormSph;
+            ypntNorthSphRot =     - znormSph*ynormSph;  // ypntNorthSphRot = 0.0 - Dist*ynormSph;
+            zpntNorthSphRot = 1.0 - znormSph*znormSph;  // zpntNorthSphRot = 1.0 - Dist*znormSph;
+            NormVector(xpntNorthSphRot, ypntNorthSphRot, zpntNorthSphRot);
+
+            // This would create in 3D the rotated Easting vector; but we don't need it in this routine.
+            // Left out to optimize the computation..
+            // CrossProd( xpntNorthSphRot, ypntNorthSphRot, zpntNorthSphRot, xnormSph, ynormSph, znormSph,
+            //            xpntEastSph,  ypntEastSphRot,  zpntEastSphRot ); //vecxRot = CrossProd(vecy,vecz)
+
+            vecAngle = acos( (xpntNorthSph*xpntNorthSphRot + ypntNorthSph*ypntNorthSphRot + zpntNorthSph*zpntNorthSphRot) ) ;
+            // Determine the sign of the angle
+            CrossProd( xpntNorthSphRot, ypntNorthSphRot, zpntNorthSphRot, xpntNorthSph, ypntNorthSph, zpntNorthSph, \
+                       xncross,  yncross,  zncross);
+            if ( (xncross*xnormSph + yncross*ynormSph + zncross*znormSph) > 0.0)  // dotProduct
+              vecAngle *=-1.0;
+
+            if ( !jScansPositively ) vecAngle += radians(180.0);  // this is needed in scanning mode 00
+
+            xpntNorthSph = sin(vecAngle);    // Rotate the point/vector (0,1) around Z-axis with vecAngle
+            ypntNorthSph = cos(vecAngle);
+            xpntEastSph  =   ypntNorthSph;   // Rotate the same point/vector around Z-axis with 90 degrees
+            ypntEastSph  =  -xpntNorthSph;
+
+            //zpntNorthSph = 0; zpntEastSph = 0;  // not needed in 2D
+
+            // 1) Build the rotation matrix and put the axes-base vectors into the matrix
+            VJaa = xpntEastSph ;
+            VJab = xpntNorthSph;
+            VJba = ypntEastSph ;
+            VJbb = ypntNorthSph;
+
+            idx4 = 4*idx;
+            // Caching the rotation matrix for later usage ..
+            rotationMatrixArray[idx4++] = VJaa;
+            rotationMatrixArray[idx4++] = VJab;
+            rotationMatrixArray[idx4++] = VJba;
+            rotationMatrixArray[idx4++] = VJbb;
+
+            if ( cdoDebugExt>=20 )
+              if ( ((i<3) && (j<3)) || ((i>(nx-3)) && (j>(ny-3))  ) )
+                {
+                  cdoPrint("grid point [%03d,%03d] with latlon[%3.6f,%3.6f]; (lon_pntNorth, lat_pntNorth) = [%3.6f,%3.6f]; dLonNorth=%3.6f; dLatNorth=%3.6f (Northing grid relative) ",
+                           i,j, lon_pnt0, lat_pnt0,lon_pntNorth, lat_pntNorth, RAD2DEG*dLonNorth, RAD2DEG*dLatNorth );
+                  cdoPrint("grid point [%03d,%03d] with latlon[%3.6f,%3.6f]; (lon_pntEast,lat_pntEast    )= [%3.6f,%3.6f]; dLonEast =%3.6f; dLatEast =%3.6f (Easting grid relative ) ",
+                           i,j, lon_pnt0, lat_pnt0,lon_pntEast,lat_pntEast, RAD2DEG*dLonEast, RAD2DEG*dLatEast );
+                  //cdoPrint("(xpntNorthSph, ypntNorthSph)= [%3.6f,%3.6f]; (xpntEastSph,ypntEastSph) = [%3.6f,%3.6f];",
+                  //         xpntNorthSph, ypntNorthSph, xpntEastSph,ypntEastSph );
+                  //vecAngle = RAD2DEG * acos( (xpntEastSph*xpntNorthSph + ypntEastSph*ypntNorthSph + zpntEastSph*zpntNorthSph) );
+                  //vecAngle = RAD2DEG * acos( (xpntEastSph*xpntNorthSph + ypntEastSph*ypntNorthSph) );
+                  cdoPrint("(xpntNorthSph, ypntNorthSph, zpntNorthSph)= [%3.6f,%3.6f,%3.6f]; (xpntEastSph,ypntEastSph, zpntEastSph) = [%3.6f,%3.6f,%3.6f]; vecAngle= %3.6f",
+                           xpntNorthSph, ypntNorthSph, zpntNorthSph, xpntEastSph, ypntEastSph, zpntEastSph, vecAngle );
+                  cdoPrint("rotation matrix for grid point [%03d,%03d] with latlon[%3.6f,%3.6f]: (VJaa, VJab, VJba, VJbb) = (%3.6f,%3.6f,%3.6f,%3.6f)",
+                           i,j, lon_pnt0, lat_pnt0, VJaa, VJab, VJba, VJbb);
+                }
+
+          } // end of for ( i = 0; i < nx; i++ )
+    }  // end of if (rotationMatrixArray== NULL)
+
+  // Take the rotation matrix from the cache
+  for ( j = 0; j < ny; j++ )
+    for ( i = 0; i < nx; i++ )
+      {
+        idx = (j*nx+i); idx4 = 4*idx;
+        VJaa = rotationMatrixArray[idx4++];
+        VJab = rotationMatrixArray[idx4++];
+        VJba = rotationMatrixArray[idx4++];
+        VJbb = rotationMatrixArray[idx4++];
+
+        // 2) Transform the UV vector with jacobian matrix
+        u = us[idx]; v = vs[idx];
+        //u = 6.0;  v = 0.0; // test: 6 m/s along the easting direction of the grid
+        magnitude=hypot(u, v);  // old vector magnitude in the model space
+        //(uu) =   (VJaa VJab) * ( u )
+        //(vv)     (VJba VJbb)   ( v )
+        uu = VJaa*u+VJab*v;
+        vv = VJba*u+VJbb*v;
+        //(uu) =   (VJaa VJab VJac) * ( u )
+        //(vv)     (VJba VJbb VJbc)   ( v )
+        //(ww)     (VJba VJbb VJcc)   ( w )
+        
+        // 3) Apply scaling of the vector so that the vector keeps the original length (model space)
+        newMagnitude = hypot(uu, vv);
+        us[idx] = uu*magnitude/newMagnitude;
+        vs[idx] = vv*magnitude/newMagnitude;
+      }
+  
+  if ( cdoDebugExt>=20 )
+    cdoPrint("%s(gridname=%s) finished.", __func__, gridNamePtr(gridInqType(gridID)));
+
+  Free(xvals);
+  Free(yvals);
+}
+
+static
+void rot_uv_back_mode64(int gridID, double *us, double *vs)
+{
+  // This function is partially based on rot_uv_back() of the CDO rotuv operator.
+  // This routine expects the data to be in scanning-mode 64.
+  // This routine gives comparable (not numerically same) results as rot_uv_north().
+  // rot_uv_back_mode64() is significantly slower than rot_uv_north().
+
+  int scanningMode = gridInqScanningMode(gridID);
+  if ( scanningMode==64 )
+    {
+      if ( cdoDebugExt>1 )
+        cdoPrint("NOTICE: Processing data with scanning mode(%d); gridID=%d", scanningMode, gridID);
+    }
+  else
+    {
+      cdoPrint("\n***\n***\n WARNING! Unsupported data scanning mode(%d); gridID=%d; For this operation we support only: 64\n"
+               "RESULT will be probably incorrect!\n***\n***", scanningMode, gridID);
+    }
+
+  double xpole = 0, ypole = 0, angle = 0;
+  if ( gridInqType(gridID) == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+    gridInqParamRLL(gridID, &xpole, &ypole, &angle);
+
+  long nlon = gridInqXsize(gridID);
+  long nlat = gridInqYsize(gridID);
+
+  double *xvals = (double *) Malloc(nlon*sizeof(double));
+  double *yvals = (double *) Malloc(nlat*sizeof(double));
+  gridInqXvals(gridID, xvals);
+  gridInqYvals(gridID, yvals);
+
+  /* Convert lat/lon units if required */
+  char units[CDI_MAX_NAME];
+  gridInqXunits(gridID, units);
+  grid_to_degree(units, 1, &xpole, "xpole");
+  grid_to_degree(units, nlon, xvals, "grid center lon");
+  gridInqYunits(gridID, units);
+  grid_to_degree(units, 1, &ypole, "ypole");
+  grid_to_degree(units, nlat, yvals, "grid center lat");
+
+  double u, v;
+  for ( long ilat = 0; ilat < nlat; ilat++ )
+    for ( long ilon = 0; ilon < nlon; ilon++ )
+      {
+        long i = ilat*nlon + ilon;
+
+        double xval = lamrot_to_lam(yvals[ilat], xvals[ilon], ypole, xpole, angle);
+        double yval = phirot_to_phi(yvals[ilat], xvals[ilon], ypole, angle);
+
+        usvs_to_uv(us[i], vs[i], yval, xval, ypole, xpole, &u, &v);
+
+        us[i] = u;
+        vs[i] = v;
+      }
+
+  Free(xvals);
+  Free(yvals);
+}
+
+static
+void project_uv_latlon(int gridID, double *us, double *vs)
+{
+  // The function project_uv_latlon() is WARPING the UV-vector from grid-relative to North-pole-relative definition
+  // in LAT-LON projection, flatten into 2D space.
+  // The resulting vectors do NOT exit in a SPHERICAL LAT-LON space
+  // BUT in a strongly WARPED (2D) LAT-LON projection space.
+  // Imagine what happens to the grid-points and grid-cells close to the poles.
+  // And what affect it has on the "grid-cell relative UV-vectors" in NON-rectangular grid-cells.
+  // This routine is VERY fast as it uses JACOBIANs.
+  // Depending on shape distorsion of each cell we see the "flow" vectors to adapt.
+  // The resulting UV-vectors can by directly plot with (2D) plotting tools in LAT-LON.
+  // Even (2D) streamlines can be used on this way transformed vectors.
+  // This function expectes scaning-mode 64.
+
+  if ( gridInqType(gridID) != GRID_CURVILINEAR )
+    cdoAbort("%s(gridname=%s) transformation grid must be GRID_CURVILINEAR!", __func__, gridNamePtr(gridInqType(gridID)));
+  // this should never happen
+
+  double xpnt0,ypnt0;
+  double xpntEast,ypntEast;
+  double xpntNorth, ypntNorth;
+  long idx;
+  int i, j;
+  double distLon;
+  double distLat;
+  double VJaa,VJab,VJba,VJbb;
+  double u,v;
+  double magnitude, newMagnitude;
+  double uu;
+  double vv;
+
+  int nx = gridInqXsize(gridID);
+  int ny = gridInqYsize(gridID);
+    
+  double *xvals = (double *) Malloc(nx*ny*sizeof(double));
+  double *yvals = (double *) Malloc(nx*ny*sizeof(double));
+  gridInqXvals(gridID, xvals);
+  gridInqYvals(gridID, yvals);
+
+  int signLon=( (xvals[1] - xvals[0]) < 0 )?-1:1;
+  int signLat=( (yvals[1] - yvals[0]) < 0 )?-1:1;
+
+  if (cdoDebugExt)
+    cdoPrint("%s(gridname=%s) .. processing grid with UV [nx*ny] (%d * %d)", __func__, gridNamePtr(gridInqType(gridID)), nx, ny );
+
+  if (gridInqSize(gridID) != (nx*ny) )
+    cdoAbort("Incorrect gridsize (%d) != nx*ny (%d * %d)", gridInqSize(gridID), nx, ny);
+  // this should never happen
+
+  for ( j = 0; j < ny; j++ )
+    for ( i = 0; i < nx; i++ )
+      {
+        idx = j*nx+i;
+        xpnt0 = xvals[idx];
+        ypnt0 = yvals[idx];
+        if ((i+1)<nx)
+          {   xpntEast = xvals[idx+1];  // longitude of grid point towards east
+            ypntEast = yvals[idx+1]; }//  latitude of grid point towards east
+        else
+          {   xpntEast = xpnt0 + 0.01*(xpnt0 - xvals[idx-1]); // at the grid border define extended gridpoint
+            ypntEast = ypnt0 + 0.01*(ypnt0 - yvals[idx-1]); }
+        if ((j+1)<ny)
+          {   xpntNorth = xvals[idx+nx];  // longitude of grid point towards north
+            ypntNorth = yvals[idx+nx]; }//  latitude of grid point towards north
+        else
+          {   xpntNorth = xpnt0 + 0.01*(xpnt0 - xvals[idx-nx]); // at the grid border define extended gridpoint
+            ypntNorth = ypnt0 + 0.01*(ypnt0 - yvals[idx-nx]); }
+        /*
+            This is the local coordinate system of a grid cell where we have (u,v) at location (xpnt0,ypnt0).
+            Gridpoint coordinates have been transformed from modelspace into LatLon space
+            using function gridToCurvilinear().
+
+            (xpntNorth, ypntNorth)
+                ^
+                |
+                |
+            (xpnt0,ypnt0) ----> (xpntEast,ypntEast)
+
+            modelXLon=modelX+deltaX;    xpntEast
+            modelYLon=modelY;           ypntEast
+            modelXLat=modelX;           xpntNorth
+            modelYLat=modelY+deltaY;    ypntNorth
+
+            distLon = hypot(modelXLon-lo, modelYLon-la);
+            distLat = hypot(modelXLat-lo, modelYLat-la);
+        */
+        ///  Basically transforms grid-relative UV into north pole relative UV (~ lat-lon space)
+        ///  u,v : grid relative (u,v) not staggered
+        // get(u); get(v)
+        // 1) Build the jacobian matrix
+        distLon = hypot(xpntEast -xpnt0, ypntEast -ypnt0);
+        distLat = hypot(xpntNorth-xpnt0, ypntNorth-ypnt0);
+        VJaa = signLon*(xpntEast-xpnt0)/distLon;
+        VJab = signLon*(xpntNorth-xpnt0)/distLat;
+        VJba = signLat*(ypntEast-ypnt0)/distLon;
+        VJbb = signLat*(ypntNorth-ypnt0)/distLat;
+        if ( cdoDebugExt>=20 )
+          if ( ((i<3) && (j<3)) || ((i>(nx-3)) && (j>(ny-3))  ) )
+            cdoPrint("Jacobian for grid point [%03d,%03d] with latlon[%3.6f,%3.6f]: (VJaa, VJab, VJba, VJbb) = (%3.6f,%3.6f,%3.6f,%3.6f)", i,j, xpnt0, ypnt0, VJaa, VJab, VJba, VJbb);
+        // 2) Transform the UV vector with jacobian matrix
+        u = us[idx]; v = vs[idx];
+        //u = 6.0;  v = 0.0; // test: 6 m/s along the easting direction of the grid
+        magnitude=hypot(u, v);  // old vector magnitude in the model space
+        uu = VJaa*u+VJab*v;
+        vv = VJba*u+VJbb*v;
+        // 3) Apply scaling of the vector so that the vector keeps the original length (model space)
+        newMagnitude = hypot(uu, vv);
+        us[idx] = uu*magnitude/newMagnitude;
+        vs[idx] = vv*magnitude/newMagnitude;
+      }
+  
+  if ( cdoDebugExt>=20 )
+    cdoPrint("%s(gridname=%s) finished.", __func__, gridNamePtr(gridInqType(gridID)));
+
+  Free(xvals);
+  Free(yvals);
+}
+
+
+void *TransformUV(int operatorID)
+{
+  int varID, levelID;
+  int varID1, varID2, nlevel1, nlevel2;
+  int gridsize = 0;
+  int code, gridID;
+  int param, ltype, level, nlevs, zaxisID;
+  int pnum, pcat, pdis;
+  int offset;
+  int chcodes[MAXARG];
+  char *chvars[MAXARG];
+  char varname[CDI_MAX_NAME];
+  double *single, *usvar = NULL, *vsvar = NULL;
+  int gridIDcurvl = -1;
+  int gridIDlastused = -1;
+
+  //Note: Already initialized by the caller! Don't call again: cdoInitialize(argument);
+
+  operatorInputArg("Pairs of u and v in the rotated system;\n usage:  rotuvNorth,u,v  -or- rotuvNorth,33,34");
+
+  int nch = operatorArgc();
+  if ( nch != 2 ) cdoAbort("Number of input arguments != 2");
+  if ( nch >= MAXARG ) cdoAbort("Number of input arguments >= %d", MAXARG);
+
+  bool lvar = false; // We have a list of codes
+  int len = (int)strlen(operatorArgv()[0]);
+  int ix = (operatorArgv()[0][0] == '-') ? 1 : 0;
+  for ( int i = ix; i < len; ++i )
+    if ( !isdigit(operatorArgv()[0][i]) )
+      {
+        lvar = true; // We have a list of variables
+        break;
+      }
+
+  if ( lvar )
+    {
+      for ( int i = 0; i < nch; i++ )
+	chvars[i] = operatorArgv()[i];
+    }
+  else
+    {
+      for ( int i = 0; i < nch; i++ )
+	chcodes[i] = parameter2int(operatorArgv()[i]);
+    }
+
+  int streamID1 = streamOpenRead(cdoStreamName(0));
+
+  int vlistID1 = streamInqVlist(streamID1);
+  int vlistID2 = vlistDuplicate(vlistID1);
+
+  int nvars = vlistNvars(vlistID1);
+  int nrecs = vlistNrecs(vlistID1);
+
+  int *recVarID   = (int *) Malloc(nrecs*sizeof(int));
+  int *recLevelID = (int *) Malloc(nrecs*sizeof(int));
+
+  int **varnmiss   = (int **) Malloc(nvars*sizeof(int *));
+  double **vardata = (double **) Malloc(nvars*sizeof(double *));
+
+  // 0: set to '0'; 1: set to '1'
+  streamGrbChangeModeUvRelativeToGrid(0); // U & V are NOT grid relative
+
+  bool lfound[MAXARG];
+  for ( int i = 0; i < nch; i++ ) lfound[i] = false;
+
+  if ( lvar )
+    {
+      for ( varID = 0; varID < nvars; varID++ )
+	{
+	  vlistInqVarName(vlistID2, varID, varname);
+	  for ( int i = 0; i < nch; i++ )
+	    if ( strcmp(varname, chvars[i]) == 0 ) lfound[i] = true;
+	}
+      for ( int i = 0; i < nch; i++ )
+	if ( ! lfound[i] ) cdoAbort("Variable %s not found!", chvars[i]);
+    }
+  else
+    {
+      for ( varID = 0; varID < nvars; varID++ )
+	{
+	  code = vlistInqVarCode(vlistID2, varID);
+	  for ( int i = 0; i < nch; i++ )
+	    if ( code == chcodes[i] ) lfound[i] = true;
+	}
+      for ( int i = 0; i < nch; i++ )
+	if ( ! lfound[i] ) cdoAbort("Code %d not found!", chcodes[i]);
+    }
+
+  int VarIsU,VarIsV;
+
+  // NOTE: Variable with codes (3[3,4],105,10) will get from CDO typically a name: "10u", resp. "10v"
+
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      varnmiss[varID] = NULL;
+      vardata[varID]  = NULL;
+      param = vlistInqVarParam(vlistID1, varID);  /*  vlistInqVarParam(int vlistID, int varID): Get the parameter number of a Variable */
+      cdiDecodeParam(param, &pnum, &pcat, &pdis);
+      code = pnum;
+      zaxisID = vlistInqVarZaxis(vlistID1, varID);
+      ltype   = zaxis2ltype(zaxisID);
+      nlevs   = zaxisInqSize(zaxisID);
+      vlistInqVarName(vlistID1, varID, varname); /* vlistInqVarName(int vlistID, int varID, char *name): Get the name of a Variable */
+
+      gridID = vlistInqVarGrid(vlistID1, varID);
+      if ( cdoDebugExt>=20 )
+        cdoPrint("Var.id [%4d] with grib code:%3d and has name: %6s; level type: %3d; number of levels: %3d; gridID: %d; zaxisID: %d",
+                 varID, code, varname, ltype, nlevs, gridID, zaxisID);
+
+      if ( ! (gridInqType(gridID) == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL) )
+        cdoAbort("Only rotated lon/lat grids supported!");
+
+      CheckVarIsU(varID,varname,code);
+      CheckVarIsV(varID,varname,code);
+      if (VarIsU || VarIsV)
+        {
+          gridsize = gridInqSize(gridID);
+          if ( cdoDebugExt )
+            cdoPrint("Allocating memory for variableID %4d (code=%3d): gridsize(%d)*nlevels(%d) = %ld [%4.3f MB]",
+                     varID, vlistInqVarCode(vlistID2, varID), gridsize, nlevs, gridsize*nlevs,gridsize*nlevs*sizeof(double)/(1024.0*1024));
+          varnmiss[varID] = (int *)    Malloc(nlevs*sizeof(int));
+          vardata[varID]  = (double *) Malloc(gridsize*nlevs*sizeof(double));
+        }
+    }
+
+  if ( cdoDebugExt )
+    cdoPrint("Neccessary memory has been allocated.");
+
+  int taxisID1 = vlistInqTaxis(vlistID1);
+  int taxisID2 = taxisDuplicate(taxisID1);
+  vlistDefTaxis(vlistID2, taxisID2);
+
+  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
+
+  streamDefVlist(streamID2, vlistID2); // from this point the stream is using a different vlistID !!!!!
+  vlistID2 = streamInqVlist(streamID2); // refresh it
+
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+    {
+      taxisCopyTimestep(taxisID2, taxisID1);
+
+      streamDefTimestep(streamID2, tsID);
+
+      if ( cdoDebugExt )
+        cdoPrint("About to read U & V data to memory. Other data will be stream-copied to the output file.");
+
+      for ( int recID = 0; recID < nrecs; recID++ )
+        {
+          streamInqRecord(streamID1, &varID, &levelID);
+          code    = vlistInqVarCode(vlistID1, varID);
+          zaxisID = vlistInqVarZaxis(vlistID1, varID);
+          ltype   = zaxis2ltype(zaxisID);
+          level = zaxisInqLevel(zaxisID, levelID);
+
+          if ( vardata[varID] == NULL )
+            {   // This means that it is not eighter U neither V.
+              recVarID[recID]   = -1;  // We will NOT record/store this field in memory
+              recLevelID[recID] = -1;
+              // We will stream-copy this data
+              streamDefRecord(streamID2, varID, levelID);
+              //if ( cdoDebugExt>10 ) cdoPrint("Copying data record.. %05d (timestep:%05d)", recID, tsID);
+              if ( cdoDebugExt>=20 )
+                cdoPrint("Stream-copy data record:    %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d)",
+                         recID, tsID, varID, code, ltype, level, levelID);
+              streamCopyRecord(streamID2, streamID1);  // cannot do this ! We have to set the flag uvGridRelative = 0
+            }
+          else
+            {
+              recVarID[recID]   = varID;
+              recLevelID[recID] = levelID;
+              gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
+              offset  = gridsize*levelID;
+              single  = vardata[varID] + offset;
+              if ( cdoDebugExt>=10 )
+                cdoPrint("Memmory-read data record:   %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d)",
+                         recID, tsID, varID, code, ltype, level, levelID);
+              streamReadRecord(streamID1, single, &varnmiss[varID][levelID]);
+              if ( varnmiss[varID][levelID] )
+                cdoAbort("Missing values unsupported for this operator!");
+            }
+        } // end of for ( recID = 0; recID < nrecs; ..
+
+      if ( cdoDebugExt )
+        cdoPrint("All neccessary U & V data are in memory. About to transform the windvectors...");
+
+      int code1, zaxisID1, ltype1;
+      int code2, zaxisID2, ltype2;
+      if ( cdoDebugExt )
+        cdoPrint("Looping over %d variables to look for U-wind..",nvars);
+
+      // find u-variables:
+      for ( varID1 = 0; varID1 < nvars; varID1++ )
+        if ( vardata[varID1] == NULL )
+          {
+            //if ( cdoDebugExt ) cdoPrint("Checking U-wind: vardata[%d]== NULL ",varID1);
+          }
+        else // This means that it is U or V.
+          {
+            code1    = vlistInqVarCode(vlistID2, varID1);
+            zaxisID1 = vlistInqVarZaxis(vlistID2, varID1);
+            ltype1   = zaxis2ltype(zaxisID1);
+            nlevel1  = zaxisInqSize(zaxisID1);
+            vlistInqVarName(vlistID2, varID1, varname);
+            CheckVarIsV(varID1,varname,code1);
+            if (VarIsV) continue;
+            if ( cdoDebugExt>=20 )
+              cdoPrint("Checking U-wind: Var.id [%4d] with grib code:%3d; name: %6s; level type: %3d; number of levels: %3d; zaxisID: %d",
+                       varID1, code1, varname, ltype1, nlevel1, zaxisID1);
+            CheckVarIsU(varID1,varname,code1);
+            if (!VarIsU) continue;
+            if ( cdoDebugExt>=10 )
+              cdoPrint("** FOUND U-wind; Var.id [%4d] with grib code:%3d; name: %6s; level type: %3d; number of levels: %3d; zaxisID: %d",
+                       varID1, code1, varname, ltype1, nlevel1, zaxisID1);
+            usvar = vardata[varID1];
+            // find corresponding v-variable to u-variable:
+            for ( varID2 = 0; varID2 < nvars; varID2++ )
+              if ( vardata[varID2]==NULL )
+                {
+                  //if ( cdoDebugExt ) cdoPrint("Checking V-wind: vardata[%d]== NULL ",varID1);
+                }
+              else // This means that it is U or V.
+                {
+                  code2    = vlistInqVarCode(vlistID2, varID2);
+                  zaxisID2 = vlistInqVarZaxis(vlistID2, varID2);
+                  ltype2   = zaxis2ltype(zaxisID2);
+                  nlevel2  = zaxisInqSize(zaxisID2);
+                  vlistInqVarName(vlistID2, varID2, varname);
+                  CheckVarIsU(varID2,varname,code2);
+                  if (VarIsU) continue;
+                  if ( cdoDebugExt>=20 )
+                    cdoPrint("Checking V-wind: Var.id [%4d] with grib code:%3d; name: %6s; level type: %3d; number of levels: %3d; zaxisID: %d",
+                             varID2, code2, varname, ltype2, nlevel2, zaxisID2);
+                  CheckVarIsV(varID2,varname,code2);
+                  if (!VarIsV) continue;
+                  if (!(( ltype1 == ltype2 ) &&  ( nlevel1 == nlevel2 ) && ( zaxisID1 == zaxisID2 )))
+                    continue;
+                  if ( cdoDebugExt>=10 )
+                    cdoPrint("** FOUND V-wind; Var.id [%4d] with grib code:%3d; name: %6s; level type: %3d; number of levels: %3d; zaxisID: %d",
+                             varID2, code2, varname, ltype1, nlevel2, zaxisID2);
+                  vsvar = vardata[varID2];
+                  if ( cdoDebugExt>=20 )
+                    cdoPrint("Using code %d [%d](u) and code %d [%d](v)",
+                             vlistInqVarCode(vlistID1, varID1), code1,
+                             vlistInqVarCode(vlistID1, varID2), code2);
+                  gridID   = vlistInqVarGrid(vlistID1, varID1);
+                  gridsize = gridInqSize(gridID);
+                  if ( operatorID != ROTUVN )  // ROTUVN operator does not need creation of gridIDcurvl ...
+                    {
+                      if  ( (gridIDcurvl != -1) && (gridIDlastused !=gridID) )
+                        cdoAbort("The gridID (%d) used just previously for uv-wind tranformation is not same this time(%d)!",gridIDlastused, gridID);
+                      
+                      if (gridIDcurvl==-1)
+                        {
+                          if ( cdoDebugExt )
+                            cdoPrint("Building LAT-LON grid for the direction to the North. (First time only).");
+                          gridIDlastused = gridID;
+                          // Compute 2D array with latlons only once. We expect that all horizontal grids for UV are same.
+                          // NOTE: At this stage U and V cannot be staggered!
+                          gridIDcurvl = gridToCurvilinear(gridID, 1);
+                          if (cdoDebugExt)
+                            cdoPrint("Transformed rotated-latLon grid (id:%d) to curvilinear (id:%d) with true lat-lon coordinates.", gridID, gridIDcurvl);
+                          // Grid definition with id: "gridIDcurvl" contains latlons of every gridpoint..
+                          // For details see: ./libcdi/src/cdi.h; Setgridtype to GRID_CURVILINEAR
+                          
+                          if ( gridIDcurvl == -1 ) cdoAbort("Creation of curvilinear grid definition failed!");
+
+                          if ( gridInqType(gridIDcurvl) != GRID_CURVILINEAR )
+                            {
+                              gridDestroy(gridIDcurvl);
+                              cdoAbort("Creation of curvilinear grid definition failed: type != GRID_CURVILINEAR");
+                            }
+                          if (cdoDebugExt)
+                            {
+                              double xpole = 0, ypole = 0, angle = 0;
+                              if ( gridInqType(gridID) == GRID_PROJECTION && gridInqProjType(gridID) == CDI_PROJ_RLL )
+                                gridInqParamRLL(gridID, &xpole, &ypole, &angle);
+                              
+                              cdoPrint("GRID_PROJECTION(id: %d) && CDI_PROJ_RLL:",gridID);
+                              cdoPrint("grid Xsize   %d, grid Ysize   %d", gridInqXsize(gridID), gridInqYsize(gridID));
+                              cdoPrint("grid Xfirst  %4.3f, grid Yfirst  %4.3f", gridInqXval(gridID, 0), gridInqYval(gridID, 0));
+                              cdoPrint("grid Xinc   %4.3f, grid Yinc   %4.3f", gridInqXinc(gridID),gridInqYinc(gridID));
+                              cdoPrint("grid Xpole   %4.3f, grid Ypole   %4.3f", xpole, ypole);
+                              cdoPrint("GRID_CURVILINEAR (id: %d):",gridIDcurvl);
+                              cdoPrint("grid Xsize   %d, grid Ysize   %d", gridInqXsize(gridIDcurvl), gridInqYsize(gridIDcurvl));
+                              cdoPrint("grid Xfirst  %4.3f, grid Yfirst  %4.3f", gridInqXval(gridIDcurvl, 0), gridInqYval(gridIDcurvl, 0));
+                              cdoPrint("grid Xlast   %4.3f, grid Ylast   %4.3f", gridInqXval(gridIDcurvl, gridInqSize(gridIDcurvl) -1), gridInqYval(gridIDcurvl, gridInqSize(gridIDcurvl) -1));
+                              if ( cdoDebugExt>=20 )
+                                {
+                                  printf("Xvals (size=%d):\n",gridInqSize(gridIDcurvl));
+                                  int ii;
+                                  for (ii=0; ii< 10; ii++)
+                                    printf("%4.3f ", gridInqXval(gridIDcurvl,ii));
+                                  printf("\n...\n");
+                                  for (ii=gridInqSize(gridIDcurvl)-10; ii< gridInqSize(gridIDcurvl); ii++)
+                                    printf("%4.3f ", gridInqXval(gridIDcurvl,ii));
+                                  printf("\n");
+                                  printf("Yvals (size=%d):\n",gridInqSize(gridIDcurvl));
+                                  for (ii=0; ii< 10; ii++)
+                                    printf("%4.3f ", gridInqYval(gridIDcurvl,ii));
+                                  printf("\n...\n");
+                                  for (ii=gridInqSize(gridIDcurvl)-10; ii< gridInqSize(gridIDcurvl); ii++)
+                                    printf("%4.3f ", gridInqYval(gridIDcurvl,ii));
+                                  printf("\n");
+                                }
+                            } // end of if (cdoDebugExt)
+                          if ( cdoDebugExt )
+                            cdoPrint("LAT-LON grid created.");
+                        }// end of if (gridIDcurvl==-1)
+                    }// end of if (operatorID != ROTUVN)
+
+                  if ( gridInqUvRelativeToGrid(gridID) != 1 )
+                    {
+                      cdoWarning("Grid with id:%d has NOT uv relative to grid. No transformation to north-pole takes place!", gridID);
+                    }
+                  else
+                    {
+                      for ( levelID = 0; levelID < nlevel1; levelID++ )
+                        {
+                          if ( cdoDebugExt ) cdoPrint("RotuvNorth(): processing  level type: %d; level %d (out of [0:%d])", ltype1, levelID, nlevel1-1);
+                          offset = gridsize*levelID;
+                          if (operatorID == ROTUVNORTH)
+                            {
+                              rot_uv_north(gridIDcurvl, usvar + offset, vsvar + offset);
+                              //rot_uv_north(gridIDlastused, usvar + offset, vsvar + offset);
+                              // transform "in-place" the uv from grid relative into north-pole related
+                            }
+                          else if (operatorID == PROJUVLATLON)
+                            project_uv_latlon(gridIDcurvl, usvar + offset, vsvar + offset);
+                          else if (operatorID == ROTUVN)
+                            rot_uv_back_mode64(gridID, usvar + offset, vsvar + offset);
+                        }
+                    }
+
+                  if ( cdoDebugExt ) cdoPrint("Finished processing level type: %d",ltype1);
+                  break;
+                } // end  for ( varID2
+          } // end  for ( varID1
+      
+      for ( int recID = 0; recID < nrecs; recID++ )
+        {
+          varID = recVarID[recID];
+          if (varID != -1)
+            {
+              levelID  = recLevelID[recID];
+              code    = vlistInqVarCode(vlistID1, varID);
+              zaxisID = vlistInqVarZaxis(vlistID1, varID);
+              ltype   = zaxis2ltype(zaxisID);
+              level = zaxisInqLevel(zaxisID, levelID);
+              if ( cdoDebugExt>=10 )
+                cdoPrint("Write modified data record: %05d (timestep:%d); Var.id [%4d]; (code=%3d; ltype=%3d; level=%4d; levelID=%3d)",
+                         recID, tsID, varID, code, ltype, level, levelID);
+              gridsize = gridInqSize(vlistInqVarGrid(vlistID1, varID));
+              offset   = gridsize*levelID;
+              single   = vardata[varID] + offset;
+
+              streamDefRecord(streamID2, varID,  levelID);
+              streamWriteRecord(streamID2, single, varnmiss[varID][levelID]);
+            }
+        }
+
+      tsID++;
+    } // end of while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
+
+  streamClose(streamID2);
+  streamClose(streamID1);
+  
+  if ( gridIDcurvl != -1 )
+    gridDestroy(gridIDcurvl);  // at the end must Free the allocated curvilinear grid definition...
+
+  for ( varID = 0; varID < nvars; varID++ )
+    {
+      if ( varnmiss[varID] ) Free(varnmiss[varID]);
+      if ( vardata[varID]  ) Free(vardata[varID]);
+    }
+
+  Free(recVarID);
+  Free(recLevelID);
+
+  cdoFinish();
+
+  return 0;
+}
+
+
+void *WindTrans(void *argument)
+{
+  cdoInitialize(argument);
+
+  UVDESTAG        = cdoOperatorAdd("uvDestag",  0, 0, NULL);
+  ROTUVNORTH      = cdoOperatorAdd("rotuvNorth",  0, 0, NULL);
+  ROTUVN          = cdoOperatorAdd("rotuvN",  0, 0, NULL);
+  PROJUVLATLON    = cdoOperatorAdd("projuvLatLon",  0, 0, NULL);  // Cylindrical Equidistant projection
+
+  int operatorID = cdoOperatorID();
+
+  if ( operatorID == ROTUVNORTH )
+    {
+      // will be calling: rot_uv_north(int gridID, double *us, double *vs);
+      return TransformUV(operatorID);
+    }
+
+  if ( operatorID == ROTUVN )
+    {
+      // will be calling: rot_uv_back_mode64(int gridID, double *us, double *vs);
+      return TransformUV(operatorID);
+    }
+
+  if ( operatorID == PROJUVLATLON )
+    {
+      // will be calling: project_uv_latlon(int gridID, double *us, double *vs)
+      return TransformUV(operatorID);
+    }
+
+  if ( operatorID == UVDESTAG )
+    {
+      return DestaggerUV();
+    }
+  
+  cdoAbort("Unexpected operatorID %d", operatorID);
+
+  return 0;
+}
diff --git a/src/after_fctrans.c b/src/after_fctrans.c
index 3541002..a00d9ad 100644
--- a/src/after_fctrans.c
+++ b/src/after_fctrans.c
@@ -46,21 +46,19 @@ long get_nfft(void)
 
 void fft_set(double *trigs, long *ifax, long n)
 {
-  long j, k, nfax, len = n;
-  long nhl;
-  double del, angle;
-
-  del = 4.0*asin(1.0) / n;
-  nhl = n / 2;
-  for ( k = 0; k < nhl; k++ )
+  long j, len = n;
+  long nhl = n / 2;
+  double del = 4.0*asin(1.0) / n;
+  double angle;
+  for ( long k = 0; k < nhl; k++ )
     {
       angle = k * del;
       trigs[2*k  ] = cos(angle);
       trigs[2*k+1] = sin(angle);
     }  
 
-  nfax = 0;
-  for (k = 0; k < 9; ++k) ifax[k] = 0;
+  long nfax = 0;
+  for ( long k = 0; k < 9; ++k ) ifax[k] = 0;
 
   ifax[9] = n;
 
@@ -82,7 +80,7 @@ void fft_set(double *trigs, long *ifax, long n)
 #if defined(__uxp__)
 #pragma loop scalar
 #endif
-  for ( k = 0; k < nfax / 2; k++ )
+  for ( long k = 0; k < nfax / 2; k++ )
     {
       j = ifax[k + 1];
       ifax[k + 1] = ifax[nfax - k];
@@ -91,7 +89,7 @@ void fft_set(double *trigs, long *ifax, long n)
 
   if ( n > 8 )
     {
-      fprintf(stderr, "fft does not work with len %ld\n", len);
+      fprintf(stderr, "FFT does not work with len=%ld (n=%ld)!\n", len, n);
       exit(1);
     }
 }
diff --git a/src/after_sptrans.c b/src/after_sptrans.c
index 777feb1..89be7bc 100644
--- a/src/after_sptrans.c
+++ b/src/after_sptrans.c
@@ -362,8 +362,7 @@ void after_legini_full(int ntr, int nlat, double *restrict poli, double *restric
 
 void after_legini(int ntr, int nlat, double *restrict poli, double *restrict pold, double *restrict coslat)
 {
-  int jgl, jm, jn, is;
-  int isp, latn, lats;
+  int is, lats;
 
   int waves  =  ntr + 1;
   int dimpnm = (ntr + 1)*(ntr + 4)/2;
@@ -374,20 +373,20 @@ void after_legini(int ntr, int nlat, double *restrict poli, double *restrict pol
   double *work = (double*) Malloc(3*waves * sizeof(double));
 
   gaussaw(gmu, gwt, nlat);
-  for ( jgl = 0; jgl < nlat; ++jgl ) gwt[jgl] *= 0.5;
+  for ( int jgl = 0; jgl < nlat; ++jgl ) gwt[jgl] *= 0.5;
 
-  for ( jgl = 0; jgl < nlat; ++jgl )
+  for ( int jgl = 0; jgl < nlat; ++jgl )
     coslat[jgl] = sqrt(1.0 - gmu[jgl]*gmu[jgl]);
 
-  for ( jgl = 0; jgl < nlat/2; jgl++ )
+  for ( int jgl = 0; jgl < nlat/2; jgl++ )
     {
       double zgwt = gwt[jgl];
 
       jspleg1(pnm, gmu[jgl], ntr, work);
 
-      latn = jgl;
-      isp = 0;
-      for ( jm = 0; jm < waves; jm++ )
+      int latn = jgl;
+      int isp = 0;
+      for ( int jm = 0; jm < waves; jm++ )
 	{
 #if defined(SX)
 #pragma vdir nodep
@@ -395,7 +394,7 @@ void after_legini(int ntr, int nlat, double *restrict poli, double *restrict pol
 #if defined(HAVE_OPENMP4)
 #pragma omp simd
 #endif
-	  for ( jn = 0; jn < waves - jm; jn++ )
+	  for ( int jn = 0; jn < waves - jm; jn++ )
 	    {
 	      is = (jn+1)%2 * 2 - 1;
 	      lats = latn - jgl + nlat - jgl - 1;
diff --git a/src/array.c b/src/array.c
index b280ad3..d9213f0 100644
--- a/src/array.c
+++ b/src/array.c
@@ -20,6 +20,29 @@ const char *fpe_errstr(int fpeRaised)
 }
 
 
+int array_minmaxsum_val(size_t len, const double *array, double *rmin, double *rmax, double *rsum)
+{
+  double min = *rmin;
+  double max = *rmax;
+  double sum = *rsum;
+
+  // #pragma omp parallel for default(none) shared(min, max, array, gridsize) reduction(+:mean)
+  // #pragma omp simd reduction(+:mean) reduction(min:min) reduction(max:max) aligned(array:16)
+  for ( size_t i = 0; i < len; ++i )
+    {
+      if ( array[i] < min ) min = array[i];
+      if ( array[i] > max ) max = array[i];
+      sum += array[i];
+    }
+    
+  if ( rmin ) *rmin = min;
+  if ( rmax ) *rmax = max;
+  if ( rsum ) *rsum = sum;
+
+  return 0;
+}
+
+
 int array_minmaxmean_val(size_t len, const double *array, double *rmin, double *rmax, double *rmean)
 {
   int excepts = FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW;
diff --git a/src/array.h b/src/array.h
index b3a092e..74ff6b6 100644
--- a/src/array.h
+++ b/src/array.h
@@ -3,6 +3,7 @@
 
 const char *fpe_errstr(int fpeRaised);
 
+int array_minmaxsum_val(size_t len, const double *array, double *rmin, double *rmax, double *rsum);
 int array_minmaxmean_val(size_t len, const double *array, double *rmin, double *rmax, double *rmean);
 
 int array_mean_val_weighted(size_t len, const double *restrict array, const double *restrict w, double missval, double *rmean);
diff --git a/src/cdo.c b/src/cdo.c
index d1f67f8..23ef3e9 100644
--- a/src/cdo.c
+++ b/src/cdo.c
@@ -58,6 +58,7 @@
 
 #include "modules.h"
 #include "error.h"
+#include "grid_proj.h"
 
 #if defined(_OPENMP)
 #  include <omp.h>
@@ -79,6 +80,14 @@ static int CDO_netcdf_hdr_pad = 0;
 static int CDO_Rusage = 0;
 static const char *username;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+void streamGrbDefDataScanningMode(int scanmode);
+#if defined (__cplusplus)
+}
+#endif
+
 void gridsearch_set_method(const char *methodstr);
 
 #define PRINT_RLIMIT(resource) \
@@ -256,6 +265,8 @@ void cdo_usage(void)
   fprintf(stderr, "    --precision <float_digits[,double_digits]>\n");
   fprintf(stderr, "                   Precision to use in displaying floating-point data (default: 7,15)\n");
   fprintf(stderr, "    --reduce_dim   Reduce NetCDF dimensions (module: TIMSTAT, FLDSTAT)\n");
+  if ( ITSME )
+    fprintf(stderr, "    --remap_genweights\n");
   fprintf(stderr, "    -R, --regular  Convert GRIB1 data from reduced to regular grid (cgribex only)\n");
   fprintf(stderr, "    -r             Generate a relative time axis\n");
   fprintf(stderr, "    -S             Create an extra output stream for the module TIMSTAT. This stream\n");
@@ -277,6 +288,10 @@ void cdo_usage(void)
   fprintf(stderr, "    -z szip        SZIP compression of GRIB1 records\n");
   fprintf(stderr, "       jpeg        JPEG compression of GRIB2 records\n");
   fprintf(stderr, "        zip[_1-9]  Deflate compression of NetCDF4 variables\n");
+#ifdef HIRLAM_EXTENSIONS
+  fprintf(stderr, "    --Dkext <debLev>   Setting debugLevel for extensions\n");
+  fprintf(stderr, "    --outputGribDataScanningMode <mode>   Setting grib scanning mode for data in output file <0, 64, 96>; Default is 64\n");
+#endif // HIRLAM_EXTENSIONS
   reset_text_color(stderr);
   fprintf(stderr, "\n");
 
@@ -1075,6 +1090,8 @@ int parse_options_long(int argc, char *argv[])
   int ltimestat_bounds;
   int lsortname;
   int lsortparam;
+  int ldebLevel;
+  int lscmode;
 
   struct cdo_option opt_long[] =
     {
@@ -1110,6 +1127,8 @@ int parse_options_long(int argc, char *argv[])
       { "table",             required_argument,                NULL, 't' },
       { "verbose",                 no_argument,                NULL, 'v' },
       { "version",                 no_argument,                NULL, 'V' },
+      { "Dkext",             required_argument,          &ldebLevel,  1  },
+      { "outputGribDataScanningMode", required_argument,  &lscmode,   1  },
       { NULL,                                0,                NULL,  0  }
     };
 
@@ -1117,6 +1136,8 @@ int parse_options_long(int argc, char *argv[])
 
   while ( 1 )
     {
+      // IMPORTANT: BY EVERY OPTION that takes arguments you MUST set its trigger variable to ZERO;
+      // otherwise the parameters of other options get wrongly assigned.
       lprecision = 0;
       lpercentile = 0;
       lnetcdf_hdr_pad = 0;
@@ -1129,6 +1150,8 @@ int parse_options_long(int argc, char *argv[])
       ltimestat_bounds = 0;
       lsortname = 0;
       lsortparam = 0;
+      ldebLevel = 0;
+      lscmode = 0;
 
       c = cdo_getopt_long(argc, argv, "f:b:e:P:g:i:k:l:m:n:t:D:z:aBCcdhLMOpQRrsSTuVvWXZ", opt_long, NULL);
       if ( c == -1 ) break;
@@ -1221,6 +1244,33 @@ int parse_options_long(int argc, char *argv[])
             {
               cdiDefGlobal("SORTPARAM", TRUE);
             }
+#ifdef HIRLAM_EXTENSIONS
+          else if ( ldebLevel )
+            {
+              int newDebLevelVal = parameter2int(CDO_optarg);
+              if ( newDebLevelVal > 0 )
+                {
+                  extern int cdiDebugExt;
+                  cdoDebugExt = newDebLevelVal;
+                  cdiDebugExt = newDebLevelVal;
+                }
+            }
+          else if ( lscmode )
+            {
+              int scanningModeValue = atoi(CDO_optarg);
+              if ( cdoDebugExt ) printf("scanningModeValue=%d\n", scanningModeValue);
+              
+              if ( (scanningModeValue==0) || (scanningModeValue==64) || (scanningModeValue==96) )
+                {
+                  streamGrbDefDataScanningMode(scanningModeValue); // -1: not used; allowed modes: <0, 64, 96>; Default is 64
+                }
+              else
+                {
+                  cdoAbort("Warning: %d not in allowed modes: <0, 64, 96>; Using default: 64\n", scanningModeValue);
+                  streamGrbDefDataScanningMode(64);
+                }
+            }
+#endif
           break;
         case 'a':
           cdoDefaultTimeType = TAXIS_ABSOLUTE;
@@ -1510,6 +1560,11 @@ int main(int argc, char *argv[])
 
   if ( cdoDefaultTableID != CDI_UNDEFID ) cdiDefTableID(cdoDefaultTableID);
 
+  extern int (*proj_lonlat_to_lcc_func)();
+  proj_lonlat_to_lcc_func = (int (*)()) proj_lonlat_to_lcc;
+  extern int (*proj_lcc_to_lonlat_func)();
+  proj_lcc_to_lonlat_func = (int (*)()) proj_lcc_to_lonlat;
+
   const char *operatorName = getOperatorName(operatorArg);
 
   if ( Help )
diff --git a/src/cdo_read.c b/src/cdo_read.c
new file mode 100644
index 0000000..d7b9b22
--- /dev/null
+++ b/src/cdo_read.c
@@ -0,0 +1,60 @@
+#include <cdi.h>
+#include "cdo_int.h"
+
+bool *cdo_read_timestepmask(const char *maskfile, int *n)
+{
+  *n = 0;
+
+  int streamID = streamOpenRead(maskfile);
+  if ( streamID == CDI_UNDEFID ) cdoAbort("Open failed on %s!", maskfile);
+
+  int vlistID = streamInqVlist(streamID);
+
+  int nvars = vlistNvars(vlistID);
+  if ( nvars > 1 ) cdoAbort("timestepmask %s contains more than one variable!", maskfile);
+
+  int gridsize = gridInqSize(vlistInqVarGrid(vlistID, 0));
+  if ( gridsize > 1 ) cdoAbort("timestepmask %s has more than one gridpoint!", maskfile);
+
+  int nlev = zaxisInqSize(vlistInqVarZaxis(vlistID, 0));
+  if ( nlev > 1 ) cdoAbort("timestepmask %s has more than one level!", maskfile);
+
+  int nts = vlistNtsteps(vlistID);
+  if ( nts == -1 )
+    {
+      nts = 0;
+      while ( streamInqTimestep(streamID, nts) ) nts++;
+
+      if ( cdoVerbose ) cdoPrint("%s: counted %i timeSteps in %s", __func__, nts, maskfile);
+
+      streamClose(streamID);
+      streamID = streamOpenRead(maskfile);
+
+    }
+  else
+    if ( cdoVerbose ) cdoPrint("%s: found %i timeSteps in %s", __func__, nts, maskfile);
+
+  *n = nts;
+  bool *imask = (bool*) Malloc(nts*sizeof(bool));
+
+  int nrecs;
+  int tsID = 0;
+  while ( (nrecs = streamInqTimestep(streamID, tsID)) )
+    {
+      if ( nrecs != 1 ) cdoAbort("Internal error; unexprected number of records!");
+
+      int varID, levelID;
+      int nmiss;
+      double value;
+      streamInqRecord(streamID, &varID, &levelID);
+      streamReadRecord(streamID, &value, &nmiss);
+      
+      imask[tsID] = !(nmiss || IS_EQUAL(value, 0));
+      
+      tsID++;  
+    }
+  
+  streamClose(streamID);
+
+  return imask;
+}
diff --git a/src/cdo_vlist.c b/src/cdo_vlist.c
index 4c95b77..470bdeb 100644
--- a/src/cdo_vlist.c
+++ b/src/cdo_vlist.c
@@ -15,11 +15,8 @@
   GNU General Public License for more details.
 */
 
-#include <stdlib.h>
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
-#include "error.h"
 
 
 double cdoZaxisInqLevel(int zaxisID, int levelID)
@@ -416,6 +413,10 @@ double *vlist_read_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlev, int
       int nlevel  = zaxisInqSize(zaxisID);
       int zaxistype = zaxisInqType(zaxisID);
 
+      if ( cdoVerbose )
+        cdoPrint("ZAXIS_HYBRID = %d ZAXIS_HYBRID_HALF=%d nlevel=%d mono_level=%d",
+                 zaxisInqType(zaxisID) == ZAXIS_HYBRID,  zaxisInqType(zaxisID) == ZAXIS_HYBRID_HALF, nlevel, mono_level);
+
       if ( (zaxistype == ZAXIS_HYBRID || zaxistype == ZAXIS_HYBRID_HALF) && nlevel > 1 && !mono_level )
 	{
 	  int l;
@@ -444,6 +445,9 @@ double *vlist_read_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlev, int
 	      
 		  vct = (double*) Malloc(nvct*sizeof(double));
 		  zaxisInqVct(zaxisID, vct);
+                  if ( cdoVerbose )
+                    cdoPrint("Detected half-level model definition : nlevel == (nvct/2 - 1) (nlevel: %d, nvct: %d, nhlevf: %d, nhlevh: %d) ",
+                             nlevel, nvct,nhlevf, nhlevh);  
 		}
 	    }
 	  else if ( nlevel == (nvct/2) )
@@ -458,6 +462,9 @@ double *vlist_read_vct(int vlistID, int *rzaxisIDh, int *rnvct, int *rnhlev, int
 	      
 		  vct = (double*) Malloc(nvct*sizeof(double));
 		  zaxisInqVct(zaxisID, vct);
+                  if ( cdoVerbose )
+                    cdoPrint("Detected full-level model definition : nlevel == (nvct/2) (nlevel: %d, nvct: %d, nhlevf: %d, nhlevh: %d) ",
+                             nlevel, nvct,nhlevf, nhlevh);  
 		}
 	    }
 	  else if ( nlevel == (nvct - 4 - 1) )
diff --git a/src/config.h.in b/src/config.h.in
index 25d540a..36906aa 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -220,6 +220,9 @@
 /* Define to 1 if you have the <wordexp.h> header file. */
 #undef HAVE_WORDEXP_H
 
+/* Define to 1 for HIRLAM extensions */
+#undef HIRLAM_EXTENSIONS
+
 /* Host name */
 #undef HOST_NAME
 
diff --git a/src/expr.c b/src/expr.c
index c0675f2..997da03 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -59,7 +59,7 @@ enum {FT_STD, FT_CONST, FT_FLD, FT_VERT, FT_COORD, FT_1C};
 #define  MVCOMPOR(x,y)  (DBL_IS_EQUAL((x),missval1) ? missval1 : COMPOR(x,y))
 
 static double f_int(double x)          { return (int)(x); }
-static double f_nint(double x)         { return (double)lround(x); }
+static double f_nint(double x)         { return round(x); }
 static double f_sqr(double x)          { return x*x;      }
 static double f_rad(double x)          { return x*M_PI/180.; }
 static double f_deg(double x)          { return x*180./M_PI; }
@@ -179,6 +179,8 @@ int get_funcID(const char *fun)
 
   if ( funcID == -1 ) cdoAbort("Function >%s< not available!", fun);
 
+  if ( strcmp(fun_sym_tbl[funcID].name, "nint") == 0 ) cdo_check_round();
+
   return funcID;
 }
 
diff --git a/src/fieldc.c b/src/fieldc.c
index ecb1f9e..97bfd72 100644
--- a/src/fieldc.c
+++ b/src/fieldc.c
@@ -120,19 +120,18 @@ void farcsub(field_type *field, double rconst)
 
 void farinv(field_type *field)
 {
-  int i, len;
   int    grid     = field->grid;
   double missval1 = field->missval;
   double missval2 = field->missval;
   double *array   = field->ptr;
 
-  len    = gridInqSize(grid);
+  int len = gridInqSize(grid);
 
-  for ( i = 0; i < len; i++ ) 
+  for ( int i = 0; i < len; i++ ) 
     array[i] = DIVMN(1.0, array[i]);
 
   field->nmiss = 0;
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     if ( DBL_IS_EQUAL(array[i], missval1) ) field->nmiss++;
 }
 
@@ -146,7 +145,7 @@ void farround(field_type *field)
   int len = gridInqSize(grid);
 
   for ( int i = 0; i < len; i++ ) 
-    array[i] = (double)lround(array[i]);
+    array[i] = round(array[i]);
 
   field->nmiss = 0;
   for ( int i = 0; i < len; i++ )
@@ -156,14 +155,13 @@ void farround(field_type *field)
 
 void farmod(field_type *field, double divisor)
 {
-  int i, len;
   int    grid     = field->grid;
   double missval1 = field->missval;
   double *array   = field->ptr;
 
-  len    = gridInqSize(grid);
+  int len = gridInqSize(grid);
 
-  for ( i = 0; i < len; i++ )
+  for ( int i = 0; i < len; i++ )
     {
       array[i] = DBL_IS_EQUAL(array[i], missval1) ? missval1 : fmod(array[i], divisor);
     }
diff --git a/src/grid.c b/src/grid.c
index 04a803f..500259e 100644
--- a/src/grid.c
+++ b/src/grid.c
@@ -30,10 +30,9 @@
 #endif
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
-#include "error.h"
 #include "grid.h"
+#include "grid_proj.h"
 
 
 int nfc_to_nlat(int nfc, int ntr)
@@ -70,7 +69,7 @@ int ntr_to_nlat(int ntr)
       /*
       int nlat2 = (int)lround(((ntr+1)*3.+1.)/2.);
       if ( nlat == nlat2 )
-	Error("Computation of latitudes failed for truncation %d", ntr);
+	cdoAbort("Computation of latitudes failed for truncation %d", ntr);
       */
     }
 
@@ -87,7 +86,7 @@ int ntr_to_nlat_linear(int ntr)
       /*
       int nlat2 = (int)lround(((ntr+1)*2.+1.)/2.);
       if ( nlat == nlat2 )
-	Error("Computation of latitudes failed for truncation %d", ntr);
+	cdoAbort("Computation of latitudes failed for truncation %d", ntr);
       */
     }
 
@@ -113,13 +112,14 @@ int nlat_to_nlon(int nlat)
       if ( n <= 8 ) break;
 
       nlon = nlon + 2;
-
+      /*
       if ( nlon > 9999 )
 	{
 	  nlon = 2 * nlat;
 	  fprintf(stderr, "FFT does not work with len %d!\n", nlon);
 	  break;
 	}
+      */
     }
 
   return nlon;
@@ -127,12 +127,12 @@ int nlat_to_nlon(int nlat)
 
 
 static
-void scale_vec(double scalefactor, long nvals, double *restrict values)
+void scale_vec(double scalefactor, size_t nvals, double *restrict values)
 {
 #if defined(_OPENMP)
 #pragma omp parallel for default(none) shared(nvals, scalefactor, values)
 #endif
-  for ( long n = 0; n < nvals; ++n )
+  for ( size_t n = 0; n < nvals; ++n )
     {
       values[n] *= scalefactor;
     }
@@ -175,7 +175,7 @@ void grid_copy_mapping(int gridID1, int gridID2)
 }
 
 
-void grid_to_radian(const char *units, long nvals, double *restrict values, const char *description)
+void grid_to_radian(const char *units, size_t nvals, double *restrict values, const char *description)
 {
   if ( cmpstr(units, "degree") == 0 )
     {
@@ -192,11 +192,11 @@ void grid_to_radian(const char *units, long nvals, double *restrict values, cons
 }
 
 
-void grid_to_degree(const char *units, long nvals, double *restrict values, const char *description)
+void grid_to_degree(const char *units, size_t nvals, double *restrict values, const char *description)
 {
   if ( cmpstr(units, "radian") == 0 )
     {
-      for ( long n = 0; n < nvals; ++n ) values[n] *= RAD2DEG;
+      for ( size_t n = 0; n < nvals; ++n ) values[n] *= RAD2DEG;
     }
   else if ( cmpstr(units, "degree") == 0 )
     {
@@ -212,7 +212,7 @@ void grid_to_degree(const char *units, long nvals, double *restrict values, cons
 int gridToZonal(int gridID1)
 {
   int gridtype = gridInqType(gridID1);
-  int gridsize = gridInqYsize(gridID1);
+  size_t gridsize = gridInqYsize(gridID1);
   int gridID2  = gridCreate(gridtype, gridsize);
 	  
   if ( gridtype == GRID_LONLAT   ||
@@ -235,7 +235,7 @@ int gridToZonal(int gridID1)
     }
   else
     {
-      Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
+      cdoAbort("Gridtype %s unsupported!", gridNamePtr(gridtype));
     }
 
   return gridID2;
@@ -245,7 +245,7 @@ int gridToZonal(int gridID1)
 int gridToMeridional(int gridID1)
 {
   int gridtype = gridInqType(gridID1);
-  int gridsize = gridInqXsize(gridID1);
+  size_t gridsize = gridInqXsize(gridID1);
   int gridID2  = gridCreate(gridtype, gridsize);
 	  
   if ( gridtype == GRID_LONLAT   ||
@@ -268,14 +268,14 @@ int gridToMeridional(int gridID1)
     }
   else
     {
-      Error("Gridtype %s unsupported!", gridNamePtr(gridtype));
+      cdoAbort("Gridtype %s unsupported!", gridNamePtr(gridtype));
     }
 
   return gridID2;
 }
 
 
-void grid_gen_corners(int n, const double* restrict vals, double* restrict corners)
+void grid_gen_corners(size_t n, const double* restrict vals, double* restrict corners)
 {
   if ( n == 1 )
     {
@@ -284,7 +284,7 @@ void grid_gen_corners(int n, const double* restrict vals, double* restrict corne
     }
   else
     {
-      for ( int i = 0; i < n-1; ++i )
+      for ( size_t i = 0; i < n-1; ++i )
 	corners[i+1] = 0.5*(vals[i] + vals[i+1]);
 
       corners[0] = 2*vals[0] - corners[1];
@@ -293,9 +293,9 @@ void grid_gen_corners(int n, const double* restrict vals, double* restrict corne
 }
 
 
-void grid_gen_bounds(int n, const double *restrict vals, double *restrict bounds)
+void grid_gen_bounds(size_t n, const double *restrict vals, double *restrict bounds)
 {
-  for ( int i = 0; i < n-1; ++i )
+  for ( size_t i = 0; i < n-1; ++i )
     {
       bounds[2*i+1]   = 0.5*(vals[i] + vals[i+1]);
       bounds[2*(i+1)] = 0.5*(vals[i] + vals[i+1]);
@@ -321,7 +321,7 @@ void grid_check_lat_borders(int n, double *ybounds)
 }
 
 
-void grid_cell_center_to_bounds_X2D(const char* xunitstr, long xsize, long ysize, const double* restrict grid_center_lon, 
+void grid_cell_center_to_bounds_X2D(const char* xunitstr, size_t xsize, size_t ysize, const double* restrict grid_center_lon, 
 				    double* restrict grid_corner_lon, double dlon)
 {
   (void)xunitstr;
@@ -331,13 +331,13 @@ void grid_cell_center_to_bounds_X2D(const char* xunitstr, long xsize, long ysize
   if ( xsize == 1 || (grid_center_lon[xsize-1]-grid_center_lon[0]+dlon) < 359 )
     cdoAbort("Cannot calculate Xbounds for %d vals with dlon = %g", xsize, dlon);
   */
-  for ( int i = 0; i < xsize; ++i )
+  for ( size_t i = 0; i < xsize; ++i )
     {
       double minlon = grid_center_lon[i] - 0.5*dlon;
       double maxlon = grid_center_lon[i] + 0.5*dlon;
-      for ( int j = 0; j < ysize; ++j )
+      for ( size_t j = 0; j < ysize; ++j )
 	{
-	  int index = (j<<2)*xsize + (i<<2);
+	  size_t index = (j<<2)*xsize + (i<<2);
 	  grid_corner_lon[index  ] = minlon;
 	  grid_corner_lon[index+1] = maxlon;
 	  grid_corner_lon[index+2] = maxlon;
@@ -378,7 +378,7 @@ double genYmax(double y1, double y2)
 
 /*****************************************************************************/
 
-void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize, const double* restrict grid_center_lat, double* restrict grid_corner_lat)
+void grid_cell_center_to_bounds_Y2D(const char* yunitstr, size_t xsize, size_t ysize, const double *restrict grid_center_lat, double *restrict grid_corner_lat)
 {
   (void)yunitstr;
 
@@ -389,7 +389,7 @@ void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize
 
   // if ( ysize == 1 ) cdoAbort("Cannot calculate Ybounds for 1 value!");
 
-  for ( int j = 0; j < ysize; ++j )
+  for ( size_t j = 0; j < ysize; ++j )
     {
       if ( ysize == 1 )
 	{
@@ -398,7 +398,7 @@ void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize
 	}
       else
 	{
-	  int index = j*xsize;
+	  size_t index = j*xsize;
 	  if ( firstlat > lastlat )
 	    {
 	      if ( j == 0 )
@@ -425,9 +425,9 @@ void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize
 	    }
 	}
 
-      for ( int i = 0; i < xsize; ++i )
+      for ( size_t i = 0; i < xsize; ++i )
 	{
-	  int index = (j<<2)*xsize + (i<<2);
+	  size_t index = (j<<2)*xsize + (i<<2);
 	  grid_corner_lat[index  ] = minlat;
 	  grid_corner_lat[index+1] = minlat;
 	  grid_corner_lat[index+2] = maxlat;
@@ -437,13 +437,13 @@ void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize
 }
 
 static
-void gridGenRotBounds(double xpole, double ypole, double angle, int nx, int ny,
+void gridGenRotBounds(double xpole, double ypole, double angle, size_t nx, size_t ny,
 		      double *xbounds, double *ybounds, double *xbounds2D, double *ybounds2D)
 {
   double minlon, maxlon;
   double minlat, maxlat;
 
-  for ( int j = 0; j < ny; j++ )
+  for ( size_t j = 0; j < ny; j++ )
     {
       if ( ybounds[0] > ybounds[1] )
 	{
@@ -456,12 +456,12 @@ void gridGenRotBounds(double xpole, double ypole, double angle, int nx, int ny,
 	  minlat = ybounds[2*j];
 	}
 
-      for ( int i = 0; i < nx; i++ )
+      for ( size_t i = 0; i < nx; i++ )
 	{
 	  minlon = xbounds[2*i];
 	  maxlon = xbounds[2*i+1];
 
-	  int index = j*4*nx + 4*i;
+	  size_t index = j*4*nx + 4*i;
 	  xbounds2D[index+0] = lamrot_to_lam(minlat, minlon, ypole, xpole, angle);
 	  xbounds2D[index+1] = lamrot_to_lam(minlat, maxlon, ypole, xpole, angle);
 	  xbounds2D[index+2] = lamrot_to_lam(maxlat, maxlon, ypole, xpole, angle);
@@ -476,19 +476,19 @@ void gridGenRotBounds(double xpole, double ypole, double angle, int nx, int ny,
 }
 
 
-void grid_gen_xbounds2D(int nx, int ny, const double *restrict xbounds, double *restrict xbounds2D)
+void grid_gen_xbounds2D(size_t nx, size_t ny, const double *restrict xbounds, double *restrict xbounds2D)
 {
 #if defined(_OPENMP)
 #pragma omp parallel for default(none) shared(nx, ny, xbounds, xbounds2D)
 #endif
-  for ( int i = 0; i < nx; ++i )
+  for ( size_t i = 0; i < nx; ++i )
     {
       double minlon = xbounds[2*i  ];
       double maxlon = xbounds[2*i+1];
 
-      for ( int j = 0; j < ny; ++j )
+      for ( size_t j = 0; j < ny; ++j )
 	{
-	  int index = j*4*nx + 4*i;
+	  size_t index = j*4*nx + 4*i;
 	  xbounds2D[index  ] = minlon;
 	  xbounds2D[index+1] = maxlon;
 	  xbounds2D[index+2] = maxlon;
@@ -498,12 +498,12 @@ void grid_gen_xbounds2D(int nx, int ny, const double *restrict xbounds, double *
 }
 
 
-void grid_gen_ybounds2D(int nx, int ny, const double *restrict ybounds, double *restrict ybounds2D)
+void grid_gen_ybounds2D(size_t nx, size_t ny, const double *restrict ybounds, double *restrict ybounds2D)
 {
 #if defined(_OPENMP)
 #pragma omp parallel for default(none) shared(nx, ny, ybounds, ybounds2D)
 #endif
-  for ( int j = 0; j < ny; ++j )
+  for ( size_t j = 0; j < ny; ++j )
     {
       double minlat, maxlat;
       if ( ybounds[0] > ybounds[1] )
@@ -517,9 +517,9 @@ void grid_gen_ybounds2D(int nx, int ny, const double *restrict ybounds, double *
 	  minlat = ybounds[2*j  ];
 	}
 
-      for ( int i = 0; i < nx; ++i )
+      for ( size_t i = 0; i < nx; ++i )
 	{
-	  int index = j*4*nx + 4*i;
+	  size_t index = j*4*nx + 4*i;
 	  ybounds2D[index  ] = minlat;
 	  ybounds2D[index+1] = minlat;
 	  ybounds2D[index+2] = maxlat;
@@ -528,354 +528,6 @@ void grid_gen_ybounds2D(int nx, int ny, const double *restrict ybounds, double *
     }
 }
 
-static
-char *gen_param(const char *fmt, ...)
-{
-  va_list args;
-  char str[256];
-
-  va_start(args, fmt);
-
-  int len = vsprintf(str, fmt, args);
-
-  va_end(args);
-
-  len++;
-  char *rstr = (char*) Malloc(len*sizeof(char));
-  memcpy(rstr, str, len*sizeof(char));
-
-  return rstr;
-}
-
-static
-void lcc_to_geo(int gridID, int gridsize, double *xvals, double *yvals)
-{
-  double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
-  int projflag, scanflag;
-  proj_info_t proj;
-
-  gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm, &projflag, &scanflag);
-  /*
-    while ( originLon < 0 ) originLon += 360;
-    while ( lonParY   < 0 ) lonParY   += 360;
-  */
-  if ( IS_NOT_EQUAL(xincm, yincm) )
-    Warning("X and Y increment must be equal on Lambert Conformal grid (Xinc = %g, Yinc = %g)\n", 
-	    xincm, yincm);
-  /*
-  if ( IS_NOT_EQUAL(lat1, lat2) )
-    Warning("Lat1 and Lat2 must be equal on Lambert Conformal grid (Lat1 = %g, Lat2 = %g)\n", 
-	    lat1, lat2);
-  */
-  map_set(PROJ_LC, originLat, originLon, xincm, lonParY, lat1, lat2, &proj);
-
-  double zlat, zlon;
-  for ( int i = 0; i < gridsize; i++ )
-    {
-      double xi = xvals[i];
-      double xj = yvals[i];
-      // status = W3FB12(xi, xj, originLat, originLon, xincm, lonParY, lat1, &zlat, &zlon);
-      ijll_lc(xi, xj, proj, &zlat, &zlon);
-      xvals[i] = zlon;
-      yvals[i] = zlat;
-    }
-}
-
-static
-void sinu_to_geo(int gridsize, double *xvals, double *yvals)
-{
-#if defined(HAVE_LIBPROJ)
-  char *params[20];
-  projUV data, res;
-
-  int nbpar = 0;
-  params[nbpar++] = gen_param("proj=sinu");
-  params[nbpar++] = gen_param("ellps=WGS84");
-
-  if ( cdoVerbose )
-    for ( int i = 0; i < nbpar; ++i )
-      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
-
-  projPJ proj = pj_init(nbpar, params);
-  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
-
-  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
-
-  /* proj->over = 1; */		/* allow longitude > 180 */
-
-  for ( int i = 0; i < gridsize; i++ )
-    {
-      data.u = xvals[i];
-      data.v = yvals[i];
-      res = pj_inv(data, proj);
-      xvals[i] = res.u*RAD2DEG;
-      yvals[i] = res.v*RAD2DEG;
-      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
-      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
-    }
-
-  pj_free(proj);
-#else
-  cdoAbort("proj4 support not compiled in!");
-#endif
-}
-
-
-void grid_def_param_sinu(int gridID)
-{
-  const char *projection = "sinusoidal";
-  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, (int)strlen(projection)+1, projection);
-  const char *mapvarname = "Sinusoidal";
-  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, (int)strlen(mapvarname)+1, mapvarname);
-
-  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", (int)strlen(projection), projection);
-}
-
-
-void grid_def_param_laea(int gridID, double a, double lon_0, double lat_0)
-{
-  const char *projection = "lambert_azimuthal_equal_area";
-  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, (int)strlen(projection)+1, projection);
-  const char *mapvarname = "Lambert_AEA";
-  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, (int)strlen(mapvarname)+1, mapvarname);
-
-  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", (int)strlen(projection), projection);
-  
-  cdiDefAttFlt(gridID, CDI_GLOBAL, "earth_radius", CDI_DATATYPE_FLT64, 1, &a);
-  cdiDefAttFlt(gridID, CDI_GLOBAL, "longitude_of_projection_origin", CDI_DATATYPE_FLT64, 1, &lon_0);
-  cdiDefAttFlt(gridID, CDI_GLOBAL, "latitude_of_projection_origin", CDI_DATATYPE_FLT64, 1, &lat_0);
-}
-
-static
-void grid_inq_param_laea(int gridID, double *a, double *lon_0, double *lat_0, double *x_0, double *y_0)
-{
-  *a = 0; *lon_0 = 0; *lat_0 = 0, *x_0 = 0, *y_0 = 0;
-
-  int gridtype = gridInqType(gridID);
-  if ( gridtype == GRID_PROJECTION )
-    {
-      const char *projection = "lambert_azimuthal_equal_area";
-      char mapping[CDI_MAX_NAME]; mapping[0] = 0;
-      cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapping);
-      if ( mapping[0] && strcmp(mapping, projection) == 0 )
-        {
-          int atttype, attlen;
-          char attname[CDI_MAX_NAME+1];
-
-          int natts;
-          cdiInqNatts(gridID, CDI_GLOBAL, &natts);
-
-          for ( int iatt = 0; iatt < natts; ++iatt )
-            {
-              cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
-
-              if ( attlen != 1 ) continue;
-
-              if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
-                {
-                  double attflt;
-                  cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, &attflt);
-                  if      ( strcmp(attname, "earth_radius") == 0 )                    *a     = attflt;
-                  else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )  *lon_0 = attflt;
-                  else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )   *lat_0 = attflt;
-                  else if ( strcmp(attname, "false_easting")  == 0 )  *x_0 = attflt;
-                  else if ( strcmp(attname, "false_northing") == 0 )  *y_0 = attflt;
-                }
-            }
-        }
-      else
-        Warning("%s mapping parameter missing!", projection);
-    }
-}
-
-static
-void grid_inq_param_lcc(int gridID, double *a, double *lon_0, double *lat_0, double *lat_1, double *lat_2, double *x_0, double *y_0)
-{
-  *a = 0; *lon_0 = 0; *lat_0 = 0; *lat_1 = 0, *lat_2 = 0, *x_0 = 0, *y_0 = 0;
-
-  int gridtype = gridInqType(gridID);
-  if ( gridtype == GRID_PROJECTION )
-    {
-      const char *projection = "lambert_conformal_conic";
-      char mapping[CDI_MAX_NAME]; mapping[0] = 0;
-      cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapping);
-      if ( mapping[0] && strcmp(mapping, projection) == 0 )
-        {
-          int atttype, attlen;
-          char attname[CDI_MAX_NAME+1];
-
-          int natts;
-          cdiInqNatts(gridID, CDI_GLOBAL, &natts);
-
-          for ( int iatt = 0; iatt < natts; ++iatt )
-            {
-              cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
-
-              if ( attlen > 2 ) continue;
-
-              if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
-                {
-                  double attflt[2];
-                  cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, attflt);
-                  if      ( strcmp(attname, "earth_radius") == 0 )                   *a     = attflt[0];
-                  else if ( strcmp(attname, "longitude_of_central_meridian") == 0 )  *lon_0 = attflt[0];
-                  else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )  *lat_0 = attflt[0];
-                  else if ( strcmp(attname, "false_easting")  == 0 )  *x_0 = attflt[0];
-                  else if ( strcmp(attname, "false_northing") == 0 )  *y_0 = attflt[0];
-                  else if ( strcmp(attname, "standard_parallel") == 0 )
-                    {
-                      *lat_1 = attflt[0];
-                      if ( attlen == 2 ) *lat_2 = attflt[1];
-                    }
-                }
-            }
-        }
-      else
-        Warning("%s mapping parameter missing!", projection);
-    }
-}
-
-static
-void laea_to_geo(int gridID, int gridsize, double *xvals, double *yvals)
-{
-#if defined(HAVE_LIBPROJ)
-  char *params[20];
-  projUV data, res;
-  
-  double a, lon_0, lat_0, x_0, y_0;
-  grid_inq_param_laea(gridID, &a, &lon_0, &lat_0, &x_0, &y_0);
-
-  int nbpar = 0;
-  params[nbpar++] = gen_param("proj=laea");
-  if ( a > 0 ) params[nbpar++] = gen_param("a=%g", a);
-  params[nbpar++] = gen_param("lon_0=%g", lon_0);
-  params[nbpar++] = gen_param("lat_0=%g", lat_0);
-  if ( IS_NOT_EQUAL(x_0,0) ) params[nbpar++] = gen_param("x_0=%g", x_0);
-  if ( IS_NOT_EQUAL(y_0,0) ) params[nbpar++] = gen_param("y_0=%g", y_0);
-
-  if ( cdoVerbose )
-    for ( int i = 0; i < nbpar; ++i )
-      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
-
-  projPJ proj = pj_init(nbpar, &params[0]);
-  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
-
-  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
-
-  /* proj->over = 1; */		/* allow longitude > 180 */
-
-  for ( int i = 0; i < gridsize; i++ )
-    {
-      data.u = xvals[i];
-      data.v = yvals[i];
-      res = pj_inv(data, proj);
-      xvals[i] = res.u*RAD2DEG;
-      yvals[i] = res.v*RAD2DEG;
-      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
-      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
-    }
-
-  pj_free(proj);
-#else
-  cdoAbort("proj4 support not compiled in!");
-#endif
-}
-
-static
-void lcc2_to_geo(int gridID, int gridsize, double *xvals, double *yvals)
-{
-#if defined(HAVE_LIBPROJ)
-  char *params[20];
-  projUV data, res;
-
-  double a, lon_0, lat_0, lat_1, lat_2, x_0, y_0;
-  grid_inq_param_lcc(gridID, &a, &lon_0, &lat_0, &lat_1, &lat_2, &x_0, &y_0);
-
-  int nbpar = 0;
-  params[nbpar++] = gen_param("proj=lcc");
-  if ( a > 0 ) params[nbpar++] = gen_param("a=%g", a);
-  params[nbpar++] = gen_param("lon_0=%g", lon_0);
-  params[nbpar++] = gen_param("lat_0=%g", lat_0);
-  params[nbpar++] = gen_param("lat_1=%g", lat_1);
-  params[nbpar++] = gen_param("lat_2=%g", lat_2);
-  if ( IS_NOT_EQUAL(x_0,0) ) params[nbpar++] = gen_param("x_0=%g", x_0);
-  if ( IS_NOT_EQUAL(y_0,0) ) params[nbpar++] = gen_param("y_0=%g", y_0);
-
-  if ( cdoVerbose )
-    for ( int i = 0; i < nbpar; ++i )
-      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
-  
-  projPJ proj = pj_init(nbpar, &params[0]);
-  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
-
-  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
-
-  /* proj->over = 1; */		/* allow longitude > 180 */
-  
-  for ( int i = 0; i < gridsize; i++ )
-    {
-      data.u = xvals[i];
-      data.v = yvals[i];
-      res = pj_inv(data, proj);
-      xvals[i] = res.u*RAD2DEG;
-      yvals[i] = res.v*RAD2DEG;
-    }
-
-  pj_free(proj);
-#else
-  cdoAbort("proj4 support not compiled in!");
-#endif
-}
-
-static
-void proj_to_geo(char *proj4param, int gridsize, double *xvals, double *yvals)
-{
-#if defined(HAVE_LIBPROJ)
-  char *params[99];
-  projUV data, res;
-
-  int nbpar;
-  for ( nbpar = 0; nbpar < 99; ++nbpar )
-    {
-      while ( *proj4param == ' ' || *proj4param == '+' ) proj4param++;
-      if ( *proj4param == 0 ) break;
-      char *cstart = proj4param;
-      while ( *proj4param != ' ' && *proj4param != 0 ) proj4param++;
-      char *cend = proj4param;
-      size_t len = cend - cstart;
-      if ( len <= 0 ) break;
-      bool lend = *cend == 0;
-      if ( !lend ) *cend = 0;
-      params[nbpar] = strdup(cstart);
-      if ( !lend ) *cend = ' ';
-    }
-
-  if ( cdoVerbose )
-    for ( int i = 0; i < nbpar; ++i )
-      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
-
-  projPJ proj = pj_init(nbpar, &params[0]);
-  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
-
-  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
-
-  for ( int i = 0; i < gridsize; i++ )
-    {
-      data.u = xvals[i];
-      data.v = yvals[i];
-      res = pj_inv(data, proj);
-      xvals[i] = res.u*RAD2DEG;
-      yvals[i] = res.v*RAD2DEG;
-      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
-      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
-    }
-
-  pj_free(proj);
-#else
-  cdoAbort("proj4 support not compiled in!");
-#endif
-}
-
 /*
  * grib_get_reduced_row: code from GRIB_API 1.10.4
  *
@@ -885,7 +537,7 @@ void proj_to_geo(char *proj4param, int gridsize, double *xvals, double *yvals)
  *
  */
 static
-void grib_get_reduced_row(long pl,double lon_first,double lon_last,long* npoints,long* ilon_first, long* ilon_last )
+void grib_get_reduced_row(long pl, double lon_first, double lon_last, long *npoints, long *ilon_first, long *ilon_last )
 {
   double dlon_first=0, dlon_last=0;
 
@@ -940,7 +592,7 @@ void grib_get_reduced_row(long pl,double lon_first,double lon_last,long* npoints
 }
 
 static
-int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast, 
+int qu2reg_subarea(size_t gridsize, int np, double xfirst, double xlast, 
 		   double *array, int *rowlon, int ny, double missval, int *iret, int lmiss, int lperio, int lveggy)
 {
   /* sub area (longitudes) */
@@ -950,7 +602,7 @@ int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast,
   long row_count;
   int rlon, nwork = 0;
   int np4 = np*4;
-  int size = 0;
+  size_t size = 0;
   int wlen;
   int ii;
 
@@ -1032,7 +684,7 @@ int qu2reg_subarea(int gridsize, int np, double xfirst, double xlast,
 void field2regular(int gridID1, int gridID2, double missval, double *array, int nmiss, int lnearest)
 {
   int gridtype = gridInqType(gridID1);
-  if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced Gaussian grid!");
+  if ( gridtype != GRID_GAUSSIAN_REDUCED ) cdoAbort("Not a reduced Gaussian grid!");
 
   int lmiss = nmiss > 0;
   int lperio = 1;
@@ -1060,7 +712,7 @@ void field2regular(int gridID1, int gridID2, double missval, double *array, int
       (void) qu2reg3_double(array, rowlon, ny, nx, missval, &iret, lmiss, lperio, lnearest);
     }
 
-  if ( gridInqSize(gridID2) != nx*ny ) Error("Gridsize differ!");
+  if ( gridInqSize(gridID2) != nx*ny ) cdoAbort("Gridsize differ!");
 
   Free(rowlon);
 }
@@ -1072,7 +724,7 @@ int gridToRegular(int gridID1)
   double *xvals = NULL;
 
   int gridtype = gridInqType(gridID1);
-  if ( gridtype != GRID_GAUSSIAN_REDUCED ) Error("Not a reduced Gaussian grid!");
+  if ( gridtype != GRID_GAUSSIAN_REDUCED ) cdoAbort("Not a reduced Gaussian grid!");
 
   int ny = gridInqYsize(gridID1);
   int np = gridInqNP(gridID1);
@@ -1203,16 +855,16 @@ char *grid_get_proj4param(int gridID)
 
 int gridToCurvilinear(int gridID1, int lbounds)
 {
-  int index;
+  size_t index;
   int gridtype = gridInqType(gridID1);
 
-  int nx = gridInqXsize(gridID1);
-  int ny = gridInqYsize(gridID1);
+  size_t nx = gridInqXsize(gridID1);
+  size_t ny = gridInqYsize(gridID1);
 
   bool lxyvals = gridInqXvals(gridID1, NULL) && gridInqYvals(gridID1, NULL);
   if ( !lxyvals ) cdoAbort("Grid coordinates missing!");
 
-  int gridsize = gridInqSize(gridID1);
+  size_t gridsize = gridInqSize(gridID1);
   int gridID2 = gridCreate(GRID_CURVILINEAR, gridsize);
   gridDefPrec(gridID2, CDI_DATATYPE_FLT32);
 
@@ -1246,7 +898,6 @@ int gridToCurvilinear(int gridID1, int lbounds)
     {
     case GRID_LONLAT:
     case GRID_GAUSSIAN:
-    case GRID_LCC:
       {
         double xpole = 0, ypole = 0, angle = 0;
 	double xscale = 1, yscale = 1;
@@ -1282,62 +933,48 @@ int gridToCurvilinear(int gridID1, int lbounds)
 	double *xvals2D = (double*) Malloc(gridsize*sizeof(double));
 	double *yvals2D = (double*) Malloc(gridsize*sizeof(double));
 
-        if ( gridtype == GRID_LCC )
-	  {
-	    for ( int j = 0; j < ny; j++ )
-	      for ( int i = 0; i < nx; i++ )
-		{
-		  xvals2D[j*nx+i] = i+1;
-		  yvals2D[j*nx+i] = j+1;
-		}
-
-	    lcc_to_geo(gridID1, gridsize, xvals2D, yvals2D);
-	  }
-	else
-	  {
-            if ( nx == 0 ) nx = 1;
-            if ( ny == 0 ) ny = 1;
+        if ( nx == 0 ) nx = 1;
+        if ( ny == 0 ) ny = 1;
 
-            xvals = (double*) Malloc(nx*sizeof(double));
-            yvals = (double*) Malloc(ny*sizeof(double));
+        xvals = (double*) Malloc(nx*sizeof(double));
+        yvals = (double*) Malloc(ny*sizeof(double));
             
-            if ( gridInqXvals(gridID1, NULL) )
-              gridInqXvals(gridID1, xvals);
-            else
-              for ( int i = 0; i < nx; ++i ) xvals[i] = 0;
+        if ( gridInqXvals(gridID1, NULL) )
+          gridInqXvals(gridID1, xvals);
+        else
+          for ( size_t i = 0; i < nx; ++i ) xvals[i] = 0;
             
-            if ( gridInqYvals(gridID1, NULL) )
-              gridInqYvals(gridID1, yvals);
-            else
-              for ( int i = 0; i < ny; ++i ) yvals[i] = 0;
+        if ( gridInqYvals(gridID1, NULL) )
+          gridInqYvals(gridID1, yvals);
+        else
+          for ( size_t i = 0; i < ny; ++i ) yvals[i] = 0;
             
-	    if ( lproj_rll )
-	      {
-                gridInqParamRLL(gridID1, &xpole, &ypole, &angle);
-                gridDefProj(gridID2, gridID1);
+        if ( lproj_rll )
+          {
+            gridInqParamRLL(gridID1, &xpole, &ypole, &angle);
+            gridDefProj(gridID2, gridID1);
 
-		for ( int j = 0; j < ny; j++ )
-		  for ( int i = 0; i < nx; i++ )
-		    {
-		      xvals2D[j*nx+i] = lamrot_to_lam(yvals[j], xvals[i], ypole, xpole, angle);
-		      yvals2D[j*nx+i] = phirot_to_phi(yvals[j], xvals[i], ypole, angle);
-		    }	    
-	      }
-	    else
-	      {
-		for ( int j = 0; j < ny; j++ )
-		  for ( int i = 0; i < nx; i++ )
-		    {
-		      xvals2D[j*nx+i] = xscale*xvals[i];
-		      yvals2D[j*nx+i] = yscale*yvals[j];
-		    }
+            for ( size_t j = 0; j < ny; j++ )
+              for ( size_t i = 0; i < nx; i++ )
+                {
+                  xvals2D[j*nx+i] = lamrot_to_lam(yvals[j], xvals[i], ypole, xpole, angle);
+                  yvals2D[j*nx+i] = phirot_to_phi(yvals[j], xvals[i], ypole, angle);
+                }	    
+          }
+        else
+          {
+            for ( size_t j = 0; j < ny; j++ )
+              for ( size_t i = 0; i < nx; i++ )
+                {
+                  xvals2D[j*nx+i] = xscale*xvals[i];
+                  yvals2D[j*nx+i] = yscale*yvals[j];
+                }
 
-		if      ( lproj_sinu ) sinu_to_geo(gridsize, xvals2D, yvals2D);
-		else if ( lproj_laea ) laea_to_geo(gridID1, gridsize, xvals2D, yvals2D);
-		else if ( lproj_lcc  ) lcc2_to_geo(gridID1, gridsize, xvals2D, yvals2D);
-		else if ( lproj4     ) proj_to_geo(proj4param, gridsize, xvals2D, yvals2D);
-	      }
-	  }
+            if      ( lproj_sinu ) cdo_sinu_to_lonlat(gridsize, xvals2D, yvals2D);
+            else if ( lproj_laea ) cdo_laea_to_lonlat(gridID1, gridsize, xvals2D, yvals2D);
+            else if ( lproj_lcc  ) cdo_lcc_to_lonlat(gridID1, gridsize, xvals2D, yvals2D);
+            else if ( lproj4     ) cdo_proj_to_lonlat(proj4param, gridsize, xvals2D, yvals2D);
+          }
 
 	gridDefXvals(gridID2, xvals2D);
 	gridDefYvals(gridID2, yvals2D);
@@ -1347,132 +984,98 @@ int gridToCurvilinear(int gridID1, int lbounds)
 
 	if ( !lbounds ) goto NO_BOUNDS;
 
-	if ( gridtype == GRID_LCC )
-	  {		
-	    double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
-	    double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
-
-	    for ( int j = 0; j < ny; j++ )
-	      for ( int i = 0; i < nx; i++ )
-		{
-		  index = j*4*nx + 4*i;
-
-		  xbounds2D[index+0] = i+1.5;
-		  ybounds2D[index+0] = j+1.5;
-
-		  xbounds2D[index+1] = i+0.5;
-		  ybounds2D[index+1] = j+1.5;
-
-		  xbounds2D[index+2] = i+0.5;
-		  ybounds2D[index+2] = j+0.5;
-
-		  xbounds2D[index+3] = i+1.5;
-		  ybounds2D[index+3] = j+0.5;
-		}
-
-	    lcc_to_geo(gridID1, 4*gridsize, xbounds2D, ybounds2D);
-
-	    gridDefXbounds(gridID2, xbounds2D);
-	    gridDefYbounds(gridID2, ybounds2D);
-
-	    Free(xbounds2D);
-	    Free(ybounds2D);
-	  }
-	else
-	  {
-	    if ( gridInqXbounds(gridID1, NULL) )
-	      {
-		xbounds = (double*) Malloc(2*nx*sizeof(double));
-		gridInqXbounds(gridID1, xbounds);
-		if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
-		  if ( check_range(2*nx, xbounds, -720, 720) )
-		    {
-		      cdoWarning("longitude bounds out of range, skipped!");
-		      Free(xbounds);
-		      xbounds = NULL;
-		    }
-	      }
-	    else if ( nx > 1 )
-	      {
-		xbounds = (double*) Malloc(2*nx*sizeof(double));
-		grid_gen_bounds(nx, xvals, xbounds);
-	      }
-
-	    if ( gridInqYbounds(gridID1, NULL) )
-	      {
-		ybounds = (double*) Malloc(2*ny*sizeof(double));
-		gridInqYbounds(gridID1, ybounds);
-		if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
-		  if ( check_range(2*ny, ybounds, -180, 180) )
-		    {
-		      cdoWarning("latitude bounds out of range, skipped!");
-		      Free(ybounds);
-		      ybounds = NULL;
-		    }
-	      }
-	    else if ( ny > 1 )
-	      {
-		ybounds = (double*) Malloc(2*ny*sizeof(double));
-		if ( lproj_sinu || lproj_laea || lproj_lcc || lproj4 )
-		  grid_gen_bounds(ny, yvals, ybounds);
-		else
-		  {
-		    grid_gen_bounds(ny, yvals, ybounds);
-		    grid_check_lat_borders(2*ny, ybounds);
-		  }
-	      }
-
-	    if ( xbounds && ybounds )
-	      {
-		double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
-		double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
-
-		if ( lproj_rll )
-		  {
-		    gridGenRotBounds(xpole, ypole, angle, nx, ny, xbounds, ybounds, xbounds2D, ybounds2D);
-		  }
-		else
-		  {
-		    if ( lproj_sinu || lproj_laea || lproj_lcc || lproj4 )
-		      {
-			for ( int j = 0; j < ny; j++ )
-			  for ( int i = 0; i < nx; i++ )
-			    {
-			      index = j*4*nx + 4*i;
-
-			      xbounds2D[index+0] = xscale*xbounds[2*i];
-			      ybounds2D[index+0] = yscale*ybounds[2*j];
-
-			      xbounds2D[index+1] = xscale*xbounds[2*i];
-			      ybounds2D[index+1] = yscale*ybounds[2*j+1];
-
-			      xbounds2D[index+2] = xscale*xbounds[2*i+1];
-			      ybounds2D[index+2] = yscale*ybounds[2*j+1];
-
-			      xbounds2D[index+3] = xscale*xbounds[2*i+1];
-			      ybounds2D[index+3] = yscale*ybounds[2*j];
-			    }
+        if ( gridInqXbounds(gridID1, NULL) )
+          {
+            xbounds = (double*) Malloc(2*nx*sizeof(double));
+            gridInqXbounds(gridID1, xbounds);
+            if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+              if ( check_range(2*nx, xbounds, -720, 720) )
+                {
+                  cdoWarning("longitude bounds out of range, skipped!");
+                  Free(xbounds);
+                  xbounds = NULL;
+                }
+          }
+        else if ( nx > 1 )
+          {
+            xbounds = (double*) Malloc(2*nx*sizeof(double));
+            grid_gen_bounds(nx, xvals, xbounds);
+          }
+
+        if ( gridInqYbounds(gridID1, NULL) )
+          {
+            ybounds = (double*) Malloc(2*ny*sizeof(double));
+            gridInqYbounds(gridID1, ybounds);
+            if ( gridtype == GRID_LONLAT || gridtype == GRID_GAUSSIAN )
+              if ( check_range(2*ny, ybounds, -180, 180) )
+                {
+                  cdoWarning("latitude bounds out of range, skipped!");
+                  Free(ybounds);
+                  ybounds = NULL;
+                }
+          }
+        else if ( ny > 1 )
+          {
+            ybounds = (double*) Malloc(2*ny*sizeof(double));
+            if ( lproj_sinu || lproj_laea || lproj_lcc || lproj4 )
+              grid_gen_bounds(ny, yvals, ybounds);
+            else
+              {
+                grid_gen_bounds(ny, yvals, ybounds);
+                grid_check_lat_borders(2*ny, ybounds);
+              }
+          }
+
+        if ( xbounds && ybounds )
+          {
+            double *xbounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+            double *ybounds2D = (double*) Malloc(4*gridsize*sizeof(double));
+
+            if ( lproj_rll )
+              {
+                gridGenRotBounds(xpole, ypole, angle, nx, ny, xbounds, ybounds, xbounds2D, ybounds2D);
+              }
+            else
+              {
+                if ( lproj_sinu || lproj_laea || lproj_lcc || lproj4 )
+                  {
+                    for ( size_t j = 0; j < ny; j++ )
+                      for ( size_t i = 0; i < nx; i++ )
+                        {
+                          index = j*4*nx + 4*i;
+
+                          xbounds2D[index+0] = xscale*xbounds[2*i];
+                          ybounds2D[index+0] = yscale*ybounds[2*j];
+
+                          xbounds2D[index+1] = xscale*xbounds[2*i];
+                          ybounds2D[index+1] = yscale*ybounds[2*j+1];
+
+                          xbounds2D[index+2] = xscale*xbounds[2*i+1];
+                          ybounds2D[index+2] = yscale*ybounds[2*j+1];
+
+                          xbounds2D[index+3] = xscale*xbounds[2*i+1];
+                          ybounds2D[index+3] = yscale*ybounds[2*j];
+                        }
 			
-			if      ( lproj_sinu ) sinu_to_geo(4*gridsize, xbounds2D, ybounds2D);
-			else if ( lproj_laea ) laea_to_geo(gridID1, 4*gridsize, xbounds2D, ybounds2D);
-			else if ( lproj_lcc  ) lcc2_to_geo(gridID1, 4*gridsize, xbounds2D, ybounds2D);
-                        else if ( lproj4     ) proj_to_geo(proj4param, 4*gridsize, xbounds2D, ybounds2D);
-		      }
-		    else
-		      {
-			grid_gen_xbounds2D(nx, ny, xbounds, xbounds2D);
-			grid_gen_ybounds2D(nx, ny, ybounds, ybounds2D);
-		      }
-		  }
+                    if      ( lproj_sinu ) cdo_sinu_to_lonlat(4*gridsize, xbounds2D, ybounds2D);
+                    else if ( lproj_laea ) cdo_laea_to_lonlat(gridID1, 4*gridsize, xbounds2D, ybounds2D);
+                    else if ( lproj_lcc  ) cdo_lcc_to_lonlat(gridID1, 4*gridsize, xbounds2D, ybounds2D);
+                    else if ( lproj4     ) cdo_proj_to_lonlat(proj4param, 4*gridsize, xbounds2D, ybounds2D);
+                  }
+                else
+                  {
+                    grid_gen_xbounds2D(nx, ny, xbounds, xbounds2D);
+                    grid_gen_ybounds2D(nx, ny, ybounds, ybounds2D);
+                  }
+              }
 		
-		gridDefXbounds(gridID2, xbounds2D);
-		gridDefYbounds(gridID2, ybounds2D);
+            gridDefXbounds(gridID2, xbounds2D);
+            gridDefYbounds(gridID2, ybounds2D);
 		
-		if ( xbounds )  Free(xbounds);
-		if ( ybounds )  Free(ybounds);
-		if ( xbounds2D) Free(xbounds2D);
-		if ( ybounds2D) Free(ybounds2D);
-	      }
+            if ( xbounds )  Free(xbounds);
+            if ( ybounds )  Free(ybounds);
+            if ( xbounds2D) Free(xbounds2D);
+            if ( ybounds2D) Free(ybounds2D);
 	  }
 
       NO_BOUNDS:
@@ -1497,7 +1100,7 @@ int gridToCurvilinear(int gridID1, int lbounds)
 }
 
 
-int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionIndexList, int nocoords, int nobounds)
+int gridToUnstructuredSelecton(int gridID1, size_t selectionSize, int *selectionIndexList, int nocoords, int nobounds)
 {
   /* transform input grid into a unstructured Version if necessary {{{ */
   int unstructuredGridID;
@@ -1506,7 +1109,7 @@ int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionInd
   else
     unstructuredGridID = gridToUnstructured(gridID1,!nobounds);
 
-  int unstructuredGridSize = gridInqSize(unstructuredGridID);
+  size_t unstructuredGridSize = gridInqSize(unstructuredGridID);
 
   int unstructuredSelectionGridID = gridCreate(GRID_UNSTRUCTURED,selectionSize);
 
@@ -1531,7 +1134,7 @@ int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionInd
   double *xvals   = (double*) Malloc(selectionSize*sizeof(double));
   double *yvals   = (double*) Malloc(selectionSize*sizeof(double));
 
-  for (int i = 0; i < selectionSize; i++)
+  for (size_t i = 0; i < selectionSize; i++)
   {
     xvals[i] = xvalsUnstructured[selectionIndexList[i]];
     yvals[i] = yvalsUnstructured[selectionIndexList[i]];
@@ -1547,16 +1150,16 @@ int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionInd
   /* copy bounds if requested {{{ */
   if ( ! nobounds )
   {
-    int nvertex                 = gridInqNvertex(unstructuredGridID);
+    size_t nvertex              = gridInqNvertex(unstructuredGridID);
     double *xbounds             = (double*) Malloc(nvertex*selectionSize*sizeof(double));
     double *ybounds             = (double*) Malloc(nvertex*selectionSize*sizeof(double));
     double *xboundsUnstructured = (double*) Malloc(nvertex*unstructuredGridSize*sizeof(double));
     double *yboundsUnstructured = (double*) Malloc(nvertex*unstructuredGridSize*sizeof(double));
     gridInqXbounds(unstructuredGridID, xboundsUnstructured);
     gridInqYbounds(unstructuredGridID, yboundsUnstructured);
-    for (int i = 0; i < selectionSize; i++)
+    for (size_t i = 0; i < selectionSize; i++)
     {
-      for (int k = 0; k < nvertex; k++)
+      for (size_t k = 0; k < nvertex; k++)
       {
         xbounds[i*nvertex+k] = xboundsUnstructured[selectionIndexList[i]*nvertex+k];
         ybounds[i*nvertex+k] = yboundsUnstructured[selectionIndexList[i]*nvertex+k];
@@ -1585,7 +1188,7 @@ int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionInd
 int gridToUnstructured(int gridID1, int lbounds)
 {
   int gridtype = gridInqType(gridID1);
-  int gridsize = gridInqSize(gridID1);
+  size_t gridsize = gridInqSize(gridID1);
   int gridID2  = gridCreate(GRID_UNSTRUCTURED, gridsize);
   gridDefPrec(gridID2, CDI_DATATYPE_FLT32);
 	  
@@ -1611,8 +1214,8 @@ int gridToUnstructured(int gridID1, int lbounds)
 
 	gridDefNvertex(gridID2, 4);
 
-	int nx = gridInqXsize(gridID1);
-	int ny = gridInqYsize(gridID1);
+	size_t nx = gridInqXsize(gridID1);
+	size_t ny = gridInqYsize(gridID1);
 	 
 	gridDefXsize(gridID2, gridsize);
 	gridDefYsize(gridID2, gridsize);
@@ -1630,8 +1233,8 @@ int gridToUnstructured(int gridID1, int lbounds)
 	  {	    
             gridInqParamRLL(gridID1, &xpole, &ypole, &angle);
 		
-	    for ( int j = 0; j < ny; j++ )
-	      for ( int i = 0; i < nx; i++ )
+	    for ( size_t j = 0; j < ny; j++ )
+	      for ( size_t i = 0; i < nx; i++ )
 		{
 		  xvals2D[j*nx+i] = lamrot_to_lam(yvals[j], xvals[i], ypole, xpole, angle);
 		  yvals2D[j*nx+i] = phirot_to_phi(yvals[j], xvals[i], ypole, angle);
@@ -1639,8 +1242,8 @@ int gridToUnstructured(int gridID1, int lbounds)
 	  }
 	else
 	  {
-	    for ( int j = 0; j < ny; j++ )
-	      for ( int i = 0; i < nx; i++ )
+	    for ( size_t j = 0; j < ny; j++ )
+	      for ( size_t i = 0; i < nx; i++ )
 		{
 		  xvals2D[j*nx+i] = xvals[i];
 		  yvals2D[j*nx+i] = yvals[j];
@@ -1723,7 +1326,7 @@ int gridToUnstructured(int gridID1, int lbounds)
       }
     case GRID_GME:
       {
-	int nv = 6;
+	size_t nv = 6;
 	double *xbounds = NULL, *ybounds = NULL;
 
         int nd, ni, ni2, ni3;
@@ -1740,13 +1343,13 @@ int gridToUnstructured(int gridID1, int lbounds)
 
 	gme_grid(lbounds, gridsize, xvals, yvals, xbounds, ybounds, imask, ni, nd, ni2, ni3);
 	
-	for ( int i = 0; i < gridsize; i++ )
+	for ( size_t i = 0; i < gridsize; i++ )
 	  {
 	    xvals[i] *= RAD2DEG;
 	    yvals[i] *= RAD2DEG;
 
 	    if ( lbounds )
-	      for ( int j = 0; j < nv; j++ )
+	      for ( size_t j = 0; j < nv; j++ )
 		{
 		  xbounds[i*nv + j] *= RAD2DEG;
 		  ybounds[i*nv + j] *= RAD2DEG;
@@ -1785,7 +1388,7 @@ int gridToUnstructured(int gridID1, int lbounds)
       }
     default:
       {
-	Error("Grid type >%s< unsupported!", gridNamePtr(gridtype));
+	cdoAbort("Grid type >%s< unsupported!", gridNamePtr(gridtype));
 	break;
       }
     }
@@ -2014,7 +1617,6 @@ int gridWeights(int gridID, double *grid_wgts)
     {
       if ( gridtype == GRID_LONLAT      ||
 	   gridtype == GRID_GAUSSIAN    ||
-	   gridtype == GRID_LCC         ||
 	   projtype == CDI_PROJ_RLL     ||
 	   projtype == CDI_PROJ_LAEA    ||
 	   projtype == CDI_PROJ_LCC     ||
diff --git a/src/grid.h b/src/grid.h
index 11d5988..4dbfaca 100644
--- a/src/grid.h
+++ b/src/grid.h
@@ -8,6 +8,8 @@
 #include <math.h>
 #include <stdbool.h>
 
+extern double grid_missval;
+
 #ifndef  M_PI
 #define  M_PI        3.14159265358979323846264338327950288  /* pi */
 #endif
@@ -37,29 +39,29 @@ void grid_def_param_sinu(int gridID);
 
 bool grid_is_distance_generic(int gridID);
 
-void grid_to_radian(const char *units, long nvals, double *restrict values, const char *description);
-void grid_to_degree(const char *units, long nvals, double *restrict values, const char *description);
+void grid_to_radian(const char *units, size_t nvals, double *restrict values, const char *description);
+void grid_to_degree(const char *units, size_t nvals, double *restrict values, const char *description);
 
-void grid_gen_corners(int n, const double* restrict vals, double* restrict corners);
-void grid_gen_bounds(int n, const double *restrict vals, double *restrict bounds);
+void grid_gen_corners(size_t n, const double* restrict vals, double* restrict corners);
+void grid_gen_bounds(size_t n, const double *restrict vals, double *restrict bounds);
 void grid_check_lat_borders(int n, double *ybounds);
 
-void grid_gen_xbounds2D(int nx, int ny, const double *restrict xbounds, double *restrict xbounds2D);
-void grid_gen_ybounds2D(int nx, int ny, const double *restrict ybounds, double *restrict ybounds2D);
+void grid_gen_xbounds2D(size_t nx, size_t ny, const double *restrict xbounds, double *restrict xbounds2D);
+void grid_gen_ybounds2D(size_t nx, size_t ny, const double *restrict ybounds, double *restrict ybounds2D);
 
-void grid_cell_center_to_bounds_X2D(const char* xunitstr, long xsize, long ysize,
-				    const double* restrict grid_center_lon, double* restrict grid_corner_lon, double dlon);
-void grid_cell_center_to_bounds_Y2D(const char* yunitstr, long xsize, long ysize,
-				    const double* restrict grid_center_lat, double* restrict grid_corner_lat);
+void grid_cell_center_to_bounds_X2D(const char* xunitstr, size_t xsize, size_t ysize,
+				    const double *restrict grid_center_lon, double *restrict grid_corner_lon, double dlon);
+void grid_cell_center_to_bounds_Y2D(const char* yunitstr, size_t xsize, size_t ysize,
+				    const double *restrict grid_center_lat, double *restrict grid_corner_lat);
 
-int  gridWeights(int gridID, double *weights);
-int  gridGenArea(int gridID, double *area);
+int gridWeights(int gridID, double *weights);
+int gridGenArea(int gridID, double *area);
 
 int referenceToGrid(int gridID);
 int gridToZonal(int gridID);
 int gridToMeridional(int gridID);
 int gridToUnstructured(int gridID, int lbounds);
-int gridToUnstructuredSelecton(int gridID1, int selectionSize, int *selectionIndexList, int nocoords ,int nobounds);
+int gridToUnstructuredSelecton(int gridID1, size_t selectionSize, int *selectionIndexList, int nocoords ,int nobounds);
 int gridToCurvilinear(int gridID, int lbounds);
 int gridCurvilinearToRegular(int gridID);
 int gridToRegular(int gridID);
@@ -90,43 +92,15 @@ double phirot_to_phi(double phis, double rlas, double polphi, double polgam);
 void usvs_to_uv(double us, double vs, double phi, double rla,
 		double polphi, double pollam, double *u, double *v);
 
+void cdo_print_grid(int gridID, int opt);
+
+// Define a de-staggered grid for U and V
+int cdo_define_destagered_grid(int gridID_u_stag, int gridID_v_stag, double *destagGridOffsets);
+
+// Define a sampled grid of another grid
+int cdo_define_sample_grid(int gridID, int sampleFactor);
 
-// Projection codes for proj_info structure:
-#define PROJ_LATLON  0
-#define PROJ_MERC    1
-#define PROJ_LC      3
-#define PROJ_PS      5
-
-
-typedef struct {
-  int       code;     // Integer code for projection type
-  double    lat1;     // SW latitude (1,1) in degrees (-90->90N)
-  double    lon1;     // SW longitude (1,1) in degrees (-180->180E)
-  double    dx;       // Grid spacing in meters at truelats, used
-                      // only for ps, lc, and merc projections
-  double    dlat;     // Lat increment for lat/lon grids
-  double    dlon;     // Lon increment for lat/lon grids
-  double    stdlon;   // Longitude parallel to y-axis (-180->180E)
-  double    truelat1; // First true latitude (all projections)
-  double    truelat2; // Second true lat (LC only)
-  double    cone;     // Cone factor for LC projections
-  double    polei;    // Computed i-location of pole point
-  double    polej;    // Computed j-location of pole point
-  double    rsw;      // Computed radius to SW corner
-  double    rebydx;   // Earth radius divided by dx
-  int       hemi;     // 1 for NH, -1 for SH
-  int       init;     // Flag to indicate if this struct is ready for use
-} proj_info_t;
-
-/* Lambert Conformal grid (new version) */
-void map_set(int proj_code, double lat1, double lon1, double dx, double stdlon,
-	     double truelat1, double truelat2, proj_info_t *proj);
-void ijll_lc(double i, double j, proj_info_t proj, double *lat, double *lon);
-
-/* Lambert Conformal grid (old version) */
-/*
-int W3FB12(double xi, double xj, double alat1, double elon1, double dx,
-	   double elonv, double alatan, double *alat, double *elon);
-*/
+// Define a sub-grid of another grid
+int cdo_define_subgrid_grid(int gridSrcID, int subI0, int subI1, int subJ0, int subJ1);
 
 #endif  /* _GRID_H */
diff --git a/src/grid_area.c b/src/grid_area.c
index 9594b13..33446d6 100644
--- a/src/grid_area.c
+++ b/src/grid_area.c
@@ -15,9 +15,7 @@
 */
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
-#include "error.h"
 #include "grid.h"
 
 
@@ -290,7 +288,6 @@ int gridGenArea(int gridID, double* area)
 
   if ( gridtype != GRID_LONLAT      &&
        gridtype != GRID_GAUSSIAN    &&
-       gridtype != GRID_LCC         &&
        projtype != CDI_PROJ_RLL     &&
        projtype != CDI_PROJ_LAEA    &&
        projtype != CDI_PROJ_SINU    &&
diff --git a/src/grid_define.c b/src/grid_define.c
new file mode 100644
index 0000000..b2ddd28
--- /dev/null
+++ b/src/grid_define.c
@@ -0,0 +1,404 @@
+#include <cdi.h>
+#include "cdo_int.h"
+#include "grid.h"
+
+/*
+ at Function  cdo_define_destagered_grid
+ at Title     Define a de-staggered grid for U and V
+
+ at Prototype int cdo_define_destagered_grid(int gridID_u_stag, int gridID_v_stag, double *destagGridOffsets)
+ at Parameter
+    @Item  grid_u_stag       Staggered grid of u-wind component
+    @Item  grid_v_stag       Staggered grid of v-wind component
+    @Item  grid_uv_destag    Destaggered grid of uv-wind
+
+ at Description
+The function @func{cdo_define_destagered_grid} defines a de-staggered grid for U and V
+
+ at EndFunction
+*/
+int cdo_define_destagered_grid(int gridID_u_stag, int gridID_v_stag, double *destagGridOffsets)
+{
+/* Example of horizontal grids (Hirlam LAMH_D11):
+     U : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.15  last = 42.35  inc = 0.1  degrees
+                        rlat      : first = -30.8  last = 24.1  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+     V : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.2  last = 42.3  inc = 0.1  degrees
+                        rlat      : first = -30.75  last = 24.15  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+=>   RESULT:
+     R : lonlat       > size      : dim = 399300  nlon = 726  nlat = 550
+                        rlon      : first = -30.2  last = 42.3  inc = 0.1  degrees
+                        rlat      : first = -30.8  last = 24.1  inc = 0.1  degrees
+                        northpole : lon = -195  lat = 30
+*/
+  if ( cdoDebugExt )
+    cdoPrint("%s(gridID_u=%d,gridID_v=%d,destagGridOffsets(%02.1f,%02.1f)) ...\n",
+             __func__, gridID_u_stag, gridID_v_stag, destagGridOffsets[0],destagGridOffsets[1]);
+
+  if ( cdoDebugExt > 1 )
+    {
+      cdo_print_grid(gridID_u_stag, 1);
+      cdo_print_grid(gridID_v_stag, 1);
+    }
+
+  int gridtype = gridInqType(gridID_u_stag);
+  int xsize = gridInqXsize(gridID_u_stag);
+  int ysize = gridInqYsize(gridID_u_stag);
+
+  double xfirst_U = gridInqXval(gridID_u_stag, 0);   // staggered grid of u-wind
+  double yfirst_U = gridInqYval(gridID_u_stag, 0);
+  double xlast_U  = gridInqXval(gridID_u_stag, xsize-1);
+  double ylast_U  = gridInqYval(gridID_u_stag, ysize-1);
+  double xfirst_V = gridInqXval(gridID_v_stag, 0);   // staggered grid of v-wind
+  double yfirst_V = gridInqYval(gridID_v_stag, 0);
+  double xlast_V  = gridInqXval(gridID_v_stag, xsize-1);
+  double ylast_V  = gridInqYval(gridID_v_stag, ysize-1);
+  double xinc     = gridInqXinc(gridID_u_stag);
+  double yinc     = gridInqYinc(gridID_u_stag);
+
+  int gridID_uv_destag = gridDuplicate(gridID_u_stag);
+
+  if ( cdoDebugExt )
+    {
+      cdo_print_grid(gridID_uv_destag, 1);
+
+      cdoPrint("%s(): (gridXsize=%d, gridYsize=%d)", __func__, xsize, ysize);
+      cdoPrint("%s(): (xfirst_U = %3.2f; yfirst_U = %3.2f); (xfirst_V = %3.2f; yfirst_V = %3.2f)", __func__, xfirst_U, yfirst_U, xfirst_V, yfirst_V);
+      cdoPrint("%s(): (xlast_U  = %3.2f; ylast_U  = %3.2f); (xlast_V  = %3.2f; ylast_V  = %3.2f)", __func__, xlast_U, ylast_U, xlast_V, ylast_V);
+    }
+
+  double xfirst = 0, xlast = 0, yfirst = 0, ylast = 0;
+  if ( IS_EQUAL(destagGridOffsets[0], -0.5) && IS_EQUAL(destagGridOffsets[1], -0.5) )
+    {
+      xfirst =  xfirst_V;
+      xlast  =  xlast_V;
+      
+      yfirst =  yfirst_U;
+      ylast  =  ylast_U;
+    }
+  else if ( IS_EQUAL(destagGridOffsets[0], 0.5) && IS_EQUAL(destagGridOffsets[1], 0.5) )
+    {
+      xfirst =  xfirst_V + xinc*destagGridOffsets[0];
+      xlast  =  xlast_V  + xinc*destagGridOffsets[0];
+
+      yfirst =  yfirst_U + yinc*destagGridOffsets[1];
+      ylast  =  ylast_U  + yinc*destagGridOffsets[1];
+    }
+  else
+    cdoAbort("%s() Unsupported destaggered grid offsets! We support only: (-0.5,-0.5) or (0.5,0.5)", __func__);
+
+  double *xvals = (double *) Malloc(xsize*sizeof(double));
+  gridGenXvals(xsize, xfirst, xlast, xinc, xvals);
+  gridDefXvals(gridID_uv_destag, xvals);
+  Free(xvals);
+  
+  double *yvals = (double *) Malloc(ysize*sizeof(double));
+  gridGenYvals(gridtype, ysize, yfirst, ylast, yinc, yvals);
+  gridDefYvals(gridID_uv_destag, yvals);
+  Free(yvals);
+  
+  if ( cdoDebugExt )
+    {
+      cdoPrint("%s():", __func__);
+      cdo_print_grid(gridID_uv_destag, 1);
+    }
+
+  return gridID_uv_destag;
+}
+
+/*
+ at Function  cdo_define_sample_grid
+ at Title     Define a sampled grid of another grid
+
+ at Prototype int cdo_define_sample_grid(int gridSrcID, int sampleFactor)
+ at Parameter
+    @Item  gridSrcID       Source grid
+    @Item  sampleFactor    sampleFactor; typically 2,3,4 ...
+
+ at Description
+The function @func{cdo_define_sample_grid} defines a sampled grid of another grid
+
+ at EndFunction
+*/
+int cdo_define_sample_grid(int gridSrcID, int sampleFactor)
+{
+/* Example of horizontal grids (Harmonie HARM36_L25):
+            #
+            # gridID 2
+            #
+            gridtype  = projection
+            gridsize  = 622521
+            xsize     = 789
+            ysize     = 789
+            xunits    = "m"
+            yunits    = "m"
+            xfirst    = 0
+            xinc      = 2500
+            yfirst    = 0
+            yinc      = 2500
+            grid_mapping = Lambert_Conformal
+            grid_mapping_name = lambert_conformal_conic
+            standard_parallel = 52.5
+            longitude_of_central_meridian = 0.
+            latitude_of_projection_origin = 52.5
+            longitudeOfFirstGridPointInDegrees = -7.89
+            latitudeOfFirstGridPointInDegrees = 42.935
+=>   RESULT:
+            #
+            # gridID 2
+            #
+            gridtype  = projection
+            gridsize  = 156025
+            xsize     = 395
+            ysize     = 395
+            xunits    = "m"
+            yunits    = "m"
+            xfirst    = 0
+            xinc      = 5000
+            yfirst    = 0
+            yinc      = 5000
+            grid_mapping = Lambert_Conformal
+            grid_mapping_name = lambert_conformal_conic
+            standard_parallel = 52.5
+            longitude_of_central_meridian = 0.
+            latitude_of_projection_origin = 52.5
+            longitudeOfFirstGridPointInDegrees = -7.89
+            latitudeOfFirstGridPointInDegrees = 42.935
+*/
+  if ( cdoDebugExt )
+    cdoPrint("%s(gridSrcID=%d, sampleFactor=%d) ...", __func__, gridSrcID, sampleFactor);
+
+  int gridtype = gridInqType(gridSrcID);
+  if ( ! (gridtype == GRID_GAUSSIAN || gridtype == GRID_LONLAT || gridtype == GRID_PROJECTION ||
+          gridtype == GRID_CURVILINEAR || gridtype == GRID_GENERIC) )
+    cdoAbort("Unsupported gridtype: %s", gridNamePtr(gridtype));
+    
+  int gridXsize = gridInqXsize(gridSrcID);
+  int gridYsize = gridInqYsize(gridSrcID);
+
+  if ( (sampleFactor<1) || (gridXsize<1) || (gridYsize<1) || (sampleFactor > (gridXsize/4) ) || (sampleFactor > (gridYsize/4)) )
+    cdoAbort("%s(): Unsupported sampleFactor (%d)! Note that: gridXsize = %d, gridYsize = %d",
+             __func__, sampleFactor, gridXsize, gridYsize);
+
+  if ( cdoDebugExt>20 ) cdo_print_grid(gridSrcID, 1);
+
+  int xsize = (gridXsize + (sampleFactor-1)) / sampleFactor; // HARM36_L25: (789 + 2-1) / 2 = 395
+  int ysize = (gridYsize + (sampleFactor-1)) / sampleFactor;
+
+  int gridID_sampled = gridCreate(gridtype, xsize*ysize);
+
+  gridDefXsize(gridID_sampled, xsize);
+  gridDefYsize(gridID_sampled, ysize);
+
+  gridDefNP(gridID_sampled, gridInqNP(gridSrcID));
+  gridDefPrec(gridID_sampled, gridInqPrec(gridSrcID));
+  if ( gridInqUvRelativeToGrid(gridSrcID) ) gridDefUvRelativeToGrid(gridID_sampled, 1);
+
+  grid_copy_attributes(gridSrcID, gridID_sampled);
+  
+  if ( gridtype == GRID_PROJECTION ) grid_copy_mapping(gridSrcID, gridID_sampled);
+
+  if ( gridInqXvals(gridSrcID, NULL) && gridInqYvals(gridSrcID, NULL) )
+    {
+      if ( gridtype == GRID_CURVILINEAR )
+        {
+          double *vals = (double *) Malloc(gridXsize*gridYsize*sizeof(double));
+          gridInqXvals(gridSrcID, vals);
+          double *pvals = vals;
+          for ( int j = 0; j < gridYsize; j += sampleFactor )
+            for ( int i = 0; i < gridXsize; i += sampleFactor )
+              *pvals++ = vals[j*gridXsize+i];
+          gridDefXvals(gridID_sampled, vals);
+          
+          gridInqYvals(gridSrcID, vals);
+          pvals = vals;
+          for ( int j = 0; j < gridYsize; j += sampleFactor )
+            for ( int i = 0; i < gridXsize; i += sampleFactor )
+              *pvals++ = vals[j*gridXsize+i];
+          gridDefYvals(gridID_sampled, vals);
+          Free(vals);
+        }
+      else
+        {
+          double *xvals = (double *) Malloc(gridXsize*sizeof(double));
+          gridInqXvals(gridSrcID, xvals);
+          for ( int i = 0, j = 0; i < gridXsize; i += sampleFactor ) xvals[j++] = xvals[i];
+          gridDefXvals(gridID_sampled, xvals);
+          Free(xvals);
+
+          double *yvals = (double *) Malloc(gridYsize*sizeof(double));
+          gridInqYvals(gridSrcID, yvals);
+          for ( int i = 0, j = 0; i < gridYsize; i += sampleFactor ) yvals[j++] = yvals[i];
+          gridDefYvals(gridID_sampled, yvals);
+          Free(yvals);
+        }
+    }
+
+  if ( cdoDebugExt>20 )
+    {
+      cdoPrint("cdo SampleGrid: define_sample_grid(): ");
+      cdo_print_grid(gridID_sampled, 1);
+    }
+
+  return gridID_sampled;
+}
+
+
+/*
+ at Function  cdo_define_subgrid_grid
+ at Title     Define a sub-grid of another grid (LCC)
+
+ at Prototype int cdo_define_subgrid_grid(int gridIDsrc, int subI0, int subI1, int subJ0, int subJ1)
+ at Parameter
+    @Item  gridSrcID                    Source grid
+    @Item  subI0,subI1, subJ0, subJ1    Sub-grid indices
+
+ at Description
+The function @func{cdo_define_subgrid_grid} defines a sub-grid of another grid (LCC)
+
+ at EndFunction
+*/
+int cdo_define_subgrid_grid(int gridSrcID, int subI0, int subI1, int subJ0, int subJ1)
+{
+/* Example of horizontal grids (Harmonie HARM36_L25):
+            #
+            # gridID 2
+            #
+            gridtype  = projection
+            gridsize  = 622521
+            xsize     = 789
+            ysize     = 789
+            xunits    = "m"
+            yunits    = "m"
+            xfirst    = 0
+            xinc      = 2500
+            yfirst    = 0
+            yinc      = 2500
+            grid_mapping = Lambert_Conformal
+            grid_mapping_name = lambert_conformal_conic
+            standard_parallel = 52.5
+            longitude_of_central_meridian = 0.
+            latitude_of_projection_origin = 52.5
+            longitudeOfFirstGridPointInDegrees = -7.89
+            latitudeOfFirstGridPointInDegrees = 42.935
+=>   RESULT:
+            #
+            # gridID 2
+            #
+            gridtype  = projection
+            gridsize  = 156025
+            xsize     = 350
+            ysize     = 350
+            xunits    = "m"
+            yunits    = "m"
+            xfirst    = 0
+            xinc      = 2500
+            yfirst    = 0
+            yinc      = 2500
+            grid_mapping = Lambert_Conformal
+            grid_mapping_name = lambert_conformal_conic
+            standard_parallel = 52.5
+            longitude_of_central_meridian = 0.
+            latitude_of_projection_origin = 52.5
+            longitudeOfFirstGridPointInDegrees = ...
+            latitudeOfFirstGridPointInDegrees = ...
+*/
+  if ( cdoDebugExt )
+    cdoPrint("%s(gridSrcID=%d, (subI0,subI1,subJ0,subJ1) = (%d,%d,%d,%d) ...",
+             __func__, gridSrcID, subI0,subI1, subJ0, subJ1 );
+
+  int gridXsize = gridInqXsize(gridSrcID);
+  int gridYsize = gridInqYsize(gridSrcID);
+  int maxIndexI = gridXsize-1;
+  int maxIndexJ = gridYsize-1;
+
+  if ( (subI0<0)      || (subI0>maxIndexI) ||
+       (subI1<=subI0) || (subI1>maxIndexI) ||
+       (subJ0<0)      || (subJ0>maxIndexJ) ||
+       (subJ1<=subJ0) || (subJ1>maxIndexJ) )
+    cdoAbort("%s() Incorrect subgrid specified!  (subI0,subI1,subJ0,subJ1) =(%d,%d,%d,%d) Note that: gridXsize = %d, gridYsize = %d", __func__, subI0,subI1, subJ0, subJ1, gridXsize, gridYsize);
+
+  int gridtype = gridInqType(gridSrcID);
+  if ( !(gridtype == GRID_PROJECTION && gridInqProjType(gridSrcID) == CDI_PROJ_LCC) )
+    cdoAbort("%s() Error; Only LCC grid is supported; use selindexbox!", __func__);
+
+  double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+
+  gridInqParamLCC(gridSrcID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+  x_0 = grid_missval;
+  y_0 = grid_missval;
+
+  if ( cdoDebugExt>20 ) cdo_print_grid(gridSrcID, 1);
+
+  if ( cdoDebugExt )
+    {
+      cdoPrint("%s() Original LCC grid:", __func__);
+      cdoPrint("grid Xsize   %d, grid Ysize   %d", gridXsize, gridYsize);
+      cdoPrint("xval_0 %4.3f, yval_0 %4.3f", xval_0, yval_0);
+    }
+  
+  int gridIDcurvl = gridToCurvilinear(gridSrcID, 1);
+
+  xval_0 = gridInqXval(gridIDcurvl, 0);
+  yval_0 = gridInqYval(gridIDcurvl, 0);
+
+  if ( cdoDebugExt )
+    {
+      cdoPrint("%s() Original LCC grid as curvilinear (with lats-lons computed):", __func__);
+      cdoPrint("grid Xsize   %d, grid Ysize   %d", gridInqXsize(gridIDcurvl), gridInqYsize(gridIDcurvl));
+      cdoPrint("grid Xfirst  %4.3f, grid Yfirst  %4.3f", gridInqXval(gridIDcurvl, 0), gridInqYval(gridIDcurvl, 0));
+      cdoPrint("grid Xlast   %4.3f, grid Ylast   %4.3f", gridInqXval(gridIDcurvl, gridInqSize(gridIDcurvl) -1), gridInqYval(gridIDcurvl, gridInqSize(gridIDcurvl) -1));
+      cdoPrint("xval_0 %4.3f, yval_0 %4.3f", xval_0, yval_0);
+    }
+
+  int xsize = subI1 - subI0 + 1;
+  int ysize = subJ1 - subJ0 + 1;
+
+  int gridID_sampled = gridCreate(gridtype, xsize*ysize);
+  
+  gridDefXsize(gridID_sampled, xsize);
+  gridDefYsize(gridID_sampled, ysize);
+  
+  if ( gridInqXvals(gridSrcID, NULL) && gridInqYvals(gridSrcID, NULL) )
+    {
+      double *xvals = (double*) Malloc(gridXsize*sizeof(double));
+      double *yvals = (double*) Malloc(gridYsize*sizeof(double));
+      gridInqXvals(gridSrcID, xvals);
+      gridInqYvals(gridSrcID, yvals);
+      gridDefXvals(gridID_sampled, xvals);
+      gridDefYvals(gridID_sampled, yvals);
+      Free(xvals);
+      Free(yvals);
+    }
+
+  gridDefNP(gridID_sampled, gridInqNP(gridSrcID));
+  gridDefPrec(gridID_sampled, gridInqPrec(gridSrcID));
+  if ( gridInqUvRelativeToGrid(gridSrcID) ) gridDefUvRelativeToGrid(gridID_sampled, 1);
+
+  grid_copy_attributes(gridSrcID, gridID_sampled);
+
+  xval_0 = gridInqXval(gridIDcurvl, subJ0*gridXsize + subI0);
+  yval_0 = gridInqYval(gridIDcurvl, subJ0*gridXsize + subI0);
+
+  if ( cdoDebugExt )
+    {
+      cdoPrint("%s()  Sub-grid:", __func__);
+      cdoPrint("grid Xsize   %d, grid Ysize   %d", gridInqXsize(gridID_sampled), gridInqYsize(gridID_sampled));
+      cdoPrint("xval_0 %4.3f, yval_0 %4.3f", xval_0, yval_0);
+    }
+
+  gridDefParamLCC(gridID_sampled, grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0);
+    
+  gridDestroy(gridIDcurvl);
+
+  if ( cdoDebugExt>20 )
+    {
+      cdoPrint("%s(): ", __func__);
+      cdo_print_grid(gridID_sampled, 1);
+    }
+    
+  return gridID_sampled;
+}
diff --git a/src/grid_lcc.c b/src/grid_lcc.c
deleted file mode 100644
index 9992c3f..0000000
--- a/src/grid_lcc.c
+++ /dev/null
@@ -1,332 +0,0 @@
-#include <stdio.h>
-#include <math.h>
-#include "grid.h"
-
-#ifndef IS_EQUAL
-#  define IS_NOT_EQUAL(x,y) (x < y || y < x)
-#  define IS_EQUAL(x,y)     (!IS_NOT_EQUAL(x,y))
-#endif
-
-#ifndef  M_PI
-#define  M_PI		3.14159265358979323846	/* pi */
-#endif
-
-const double pi = M_PI;
-#define deg_per_rad  (180./pi)
-#define rad_per_deg  (pi / 180.)
-
-// Mean Earth Radius in m.  The value below is consistent with NCEP's routines and grids.
-const double earth_radius_m = 6371200.;
-// const double earth_radius_m = 6370000.; //  consistent with rest of MM5 system
-#define radians_per_degree  (pi / 180.)
- 
-
-static
-void map_init(proj_info_t *proj)
-{
-  // Initializes the map projection structure to missing values
-
-  proj->lat1     = -999.9;
-  proj->lon1     = -999.9;
-  proj->dx       = -999.9;
-  proj->stdlon   = -999.9;
-  proj->truelat1 = -999.9;
-  proj->truelat2 = -999.9;
-  proj->cone     = -999.9;
-  proj->polei    = -999.9;
-  proj->polej    = -999.9;
-  proj->rsw      = -999.9;
-  proj->hemi     = 0;
-  proj->init     = 0;
-}
-
-static
-double lc_cone(double truelat1, double truelat2)
-{
-  // Subroutine to compute the cone factor of a Lambert Conformal projection
-    
-  // Input Args
-  //    truelat1   (-90 -> 90 degrees N)
-  //    truelat2     "   "  "   "     "
-
-  // First, see if this is a secant or tangent projection.  For tangent
-  // projections, truelat1 = truelat2 and the cone is tangent to the 
-  // Earth's surface at this latitude.  For secant projections, the cone
-  // intersects the Earth's surface at each of the distinctly different
-  // latitudes
-
-  double cone;
-
-  if (fabs(truelat1-truelat2) > 0.1)
-    {
-      cone = log10(cos(truelat1*rad_per_deg)) - 
-  	     log10(cos(truelat2*rad_per_deg));
-      cone = cone /(log10(tan((45.0 - fabs(truelat1)/2.0) * rad_per_deg)) -
-		    log10(tan((45.0 - fabs(truelat2)/2.0) * rad_per_deg)));   
-    }
-  else
-    {
-      cone = sin(fabs(truelat1)*rad_per_deg);
-    }
-
-  return cone;
-}
-
-static
-void set_lc(proj_info_t *proj)
-{
-  // Initialize the remaining items in the proj structure for a
-  // lambert conformal grid.
-
-  double  arg;
-  double  deltalon1;
-  double  tl1r;
-  double  ctl1r;
-
-  // Compute cone factor
-  proj->cone = lc_cone(proj->truelat1, proj->truelat2);
-  // fprintf(stdout, "Computed cone factor: %g\n", proj->cone);
-
-  // Compute longitude differences and ensure we stay out of the
-  // forbidden "cut zone"
-  deltalon1 = proj->lon1 - proj->stdlon;
-  if (deltalon1 > +180.) deltalon1 = deltalon1 - 360.;
-  if (deltalon1 < -180.) deltalon1 = deltalon1 + 360.;
-
-  // Convert truelat1 to radian and compute COS for later use
-  tl1r = proj->truelat1 * rad_per_deg;
-  ctl1r = cos(tl1r);
-
-  // Compute the radius to our known lower-left (SW) corner
-  proj->rsw = proj->rebydx * ctl1r/proj->cone *
-    pow((tan((90.*proj->hemi-proj->lat1)*rad_per_deg/2.) /
-	 tan((90.*proj->hemi-proj->truelat1)*rad_per_deg/2.)), proj->cone);
-
-  // Find pole point
-  arg = proj->cone*(deltalon1*rad_per_deg);
-  proj->polei = 1. - proj->hemi * proj->rsw * sin(arg);
-  proj->polej = 1. + proj->rsw * cos(arg)  ;
-  // fprintf(stdout, "Computed pole (x,y) = %g %g\n", proj->polei, proj->polej);
-}
-
-
-void map_set(int proj_code, double lat1, double lon1, double dx, double stdlon,
-	     double truelat1, double truelat2, proj_info_t *proj)
-{
-  // Given a partially filled proj_info structure, this routine computes
-  // polei, polej, rsw, and cone (if LC projection) to complete the 
-  // structure.  This allows us to eliminate redundant calculations when
-  // calling the coordinate conversion routines multiple times for the
-  // same map.
-  // This will generally be the first routine called when a user wants
-  // to be able to use the coordinate conversion routines, and it
-  // will call the appropriate subroutines based on the 
-  // proj->code which indicates which projection type  this is.
-    
-  // First, check for validity of mandatory variables in proj
-  /*
-  if ( fabs(lat1) > 90. ) {
-    PRINT '(A)', 'Latitude of origin corner required as follows:'
-      PRINT '(A)', '    -90N <= lat1 < = 90.N'
-      STOP 'MAP_INIT'
-    }
-    if ( fabs(lon1) > 180.) {
-      PRINT '(A)', 'Longitude of origin required as follows:'
-      PRINT '(A)', '   -180E <= lon1 <= 180W'
-      STOP 'MAP_INIT'
-    }
-    if ((dx <= 0.).AND.(proj_code .NE. PROJ_LATLON)) {
-      PRINT '(A)', 'Require grid spacing (dx) in meters be positive//'
-      STOP 'MAP_INIT'
-    }
-    if ((fabs(stdlon) > 180.).AND.(proj_code != PROJ_MERC)) {
-      PRINT '(A)', 'Need orientation longitude (stdlon) as: '
-      PRINT '(A)', '   -180E <= lon1 <= 180W' 
-      STOP 'MAP_INIT'
-    }
-    if (fabs(truelat1)>90.) {
-      PRINT '(A)', 'Set true latitude 1 for all projections//'
-      STOP 'MAP_INIT'
-    }
-  */
-  map_init(proj);
-
-  proj->code     = proj_code;
-  proj->lat1     = lat1;
-  proj->lon1     = lon1;
-  proj->dx       = dx;
-  proj->stdlon   = stdlon;
-  proj->truelat1 = truelat1;
-  proj->truelat2 = truelat2;
-
-  if ( proj->code != PROJ_LATLON )
-    {
-      proj->dx = dx;
-      if (truelat1 < 0.)
-	proj->hemi = -1;
-      else
-	proj->hemi =  1;
-
-      proj->rebydx = earth_radius_m / dx;
-    }
-  /*
- pick_proj: SELECT CASE(proj->code)
-
-      CASE(PROJ_PS)
-        PRINT '(A)', 'Setting up POLAR STEREOGRAPHIC map...'
-        CALL set_ps(proj)
-
-      CASE(PROJ_LC)
-  */
-  // fprintf(stdout, "Setting up LAMBERT CONFORMAL map...\n");
-  if (fabs(proj->truelat2) > 90.)
-    {
-      // fprintf(stdout, "Second true latitude not set, assuming a tangent\n");
-      // fprintf(stdout, "projection at truelat1: %g\n", proj->truelat1);
-      proj->truelat2 = proj->truelat1;
-    }
-
-  set_lc(proj);
-  /*
-      CASE (PROJ_MERC)
-        PRINT '(A)', 'Setting up MERCATOR map...'
-        CALL set_merc(proj)
-   
-      CASE (PROJ_LATLON)
-        PRINT '(A)', 'Setting up CYLINDRICAL EQUIDISTANT LATLON map...'
-        // Convert lon1 to 0->360 notation
-        if (proj->lon1 < 0.) proj->lon1 = proj->lon1 + 360.
-   
-      CASE DEFAULT
-        PRINT '(A,I2)', 'Unknown projection code: ', proj->code
-        STOP 'MAP_INIT'
-    
-    END SELECT pick_proj
-  */
-
-  proj->init = 1;
-}
-
-
-void ijll_lc(double i, double j, proj_info_t proj, double *lat, double *lon)
-{
-  // Subroutine to convert from the (i,j) cartesian coordinate to the 
-  // geographical latitude and longitude for a Lambert Conformal projection.
-
-  // History:
-  // 25 Jul 01: Corrected by B. Shaw, NOAA/FSL
-  // 10 Sep 09: Converted to ANSI C: Uwe Schulzweida, MPIMET
-
-  // Input Args
-  // double, INTENT(IN)              :: i        // Cartesian X coordinate
-  // double, INTENT(IN)              :: j        // Cartesian Y coordinate
-  // TYPE(proj_info),INTENT(IN)      :: proj     // Projection info structure
-
-  // Output Args                 
-  // double, INTENT(OUT)             :: lat      // Latitude (-90->90 deg N)
-  // double, INTENT(OUT)             :: lon      // Longitude (-180->180 E)
-
-  // Locals 
-  double  inew;
-  double  jnew;
-  double  r;
-  double  chi,chi1,chi2;
-  double  r2;
-  double  xx;
-  double  yy;
-
-  chi1 = (90. - proj.hemi*proj.truelat1)*rad_per_deg;
-  chi2 = (90. - proj.hemi*proj.truelat2)*rad_per_deg;
-    
-  // See if we are in the southern hemispere and flip the indices if we are. 
-  if ( proj.hemi == -1 )
-    { 
-      inew = -i + 2.;
-      jnew = -j + 2.;
-    }
-  else
-    {
-      inew = i;
-      jnew = j;
-    }
-
-  // Compute radius**2 to i/j location
-  xx = inew - proj.polei;
-  yy = proj.polej - jnew;
-  r2 = (xx*xx + yy*yy);
-  r  = sqrt(r2)/proj.rebydx;
-   
-  // Convert to lat/lon
-  if ( IS_EQUAL(r2, 0.) )
-    {
-      *lat = proj.hemi * 90.;
-      *lon = proj.stdlon;
-    }
-  else
-    {
-      // Longitude
-      *lon = proj.stdlon + deg_per_rad * atan2(proj.hemi*xx,yy)/proj.cone;
-      *lon = fmod(*lon+360., 360.);
-
-      // Latitude.  Latitude determined by solving an equation adapted 
-      // from:
-      //  Maling, D.H., 1973: Coordinate Systems and Map Projections
-      // Equations #20 in Appendix I.  
-        
-      if ( IS_EQUAL(chi1, chi2) )
-	chi = 2.0*atan( pow( r/tan(chi1), (1./proj.cone) ) * tan(chi1*0.5) );
-      else
-	chi = 2.0*atan( pow( r*proj.cone/sin(chi1), (1./proj.cone) ) * tan(chi1*0.5)) ;
-
-      *lat = (90.0-chi*deg_per_rad)*proj.hemi;
-    }
-
-  if ( *lon > +180. ) *lon = *lon - 360.;
-  if ( *lon < -180. ) *lon = *lon + 360.;
-}
-
-/*
-int main(void)
-{
-  int    status = 0;
-  int    nlon = 245;
-  int    nlat = 277;
-  double xi, xj;
-  double lat_ll_p   =  47.806;
-  double lon_ll_p   = -10.063;
-  double lat_tan_p  =  59.2;
-  double dx_p       =  11000.0;
-  double lon_xx_p   = -10.0;
-  double zlat, zlon;
-  proj_info_t proj;
-
-  map_set(PROJ_LC, lat_ll_p, 360.+lon_ll_p, dx_p, 360.+lon_xx_p, lat_tan_p, lat_tan_p, &proj);
-
-  xi = 1;
-  xj = 1;
-  ijll_lc(xi, xj, proj, &zlat, &zlon);
-  printf("1 1 47.806 349.937 0\n");
-  printf("%g %g %g %g %d\n", xj, xi, zlat, zlon, status);
-
-  xi = nlon;
-  xj = nlat;
-  ijll_lc(xi, xj, proj, &zlat, &zlon);
-  printf("277 245 63.086 51.4192 0\n");
-  printf("%g %g %g %g %d\n", xj, xi, zlat, zlon, status);
-			  
-
-  {
-    int i, j;
-    for ( j = 1; j <= nlat; j++ )
-      for ( i = 1; i <= nlon; i++ )
-	{
-	  xi = i;
-	  xj = j;
-	  ijll_lc(xi, xj, proj, &zlat, &zlon);
-	  if ( zlon < 0 ) zlon+=360;
-	}
-  }
-			
-  return 0;
-}
-*/
diff --git a/src/grid_print.c b/src/grid_print.c
index f6a6fb2..ea9be38 100644
--- a/src/grid_print.c
+++ b/src/grid_print.c
@@ -334,6 +334,18 @@ void grid_print_kernel(int gridID, int opt, FILE *fp)
             Free(rowlon);
           }
 
+
+        int uvRelativeToGrid = gridInqUvRelativeToGrid(gridID);
+        if ( uvRelativeToGrid > 0 )
+          fprintf(fp, "uvRelativeToGrid = %d\n", uvRelativeToGrid);
+
+#ifdef HIRLAM_EXTENSIONS
+        {
+          int scanningMode = gridInqScanningMode(gridID);
+          fprintf(fp, "scanningMode = %d\n", scanningMode);
+        }
+#endif // HIRLAM_EXTENSIONS
+
         if ( type == GRID_PROJECTION )
           {
             attstr[0] = 0; cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, attstr);
@@ -345,27 +357,6 @@ void grid_print_kernel(int gridID, int opt, FILE *fp)
 
 	break;
       }
-    case GRID_LCC:
-      {
-	double originLon = 0, originLat = 0, lonParY = 0, lat1 = 0, lat2 = 0, xincm = 0, yincm = 0;
-	int projflag = 0, scanflag = 0;
-	gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                        &projflag, &scanflag);
-
-	fprintf(fp,
-                "originLon = %.*g\n"
-                "originLat = %.*g\n"
-                "lonParY   = %.*g\n"
-                "lat1      = %.*g\n"
-                "lat2      = %.*g\n"
-                "xinc      = %.*g\n"
-                "yinc      = %.*g\n"
-                "projection = %s\n",
-                dig, originLon, dig, originLat, dig, lonParY,
-                dig, lat1, dig, lat2, dig, xincm, dig, yincm,
-                (projflag & 128) == 0 ? "northpole" : "southpole");
-	break;
-      }
     case GRID_SPECTRAL:
       {
         fprintf(fp, "truncation = %d\n"
@@ -381,7 +372,7 @@ void grid_print_kernel(int gridID, int opt, FILE *fp)
       {
         int nd, ni, ni2, ni3;
         gridInqParamGME(gridID, &nd, &ni, &ni2, &ni3);
-        fprintf(fp, "ni        = %d\n", ni );
+        fprintf(fp, "ni        = %d\n", ni);
         break;
       }
    default:
@@ -408,7 +399,7 @@ void grid_print_kernel(int gridID, int opt, FILE *fp)
       static const char prefix[] = "mask      = ";
       printMask(fp, prefix, sizeof(prefix)-1, (size_t)(gridsize > 0 ? gridsize : 0), mask);
       if ( mask ) Free(mask);
-    }
+    }    
 
   int projID = gridInqProj(gridID);
   if ( projID != CDI_UNDEFID && gridInqType(projID) == GRID_PROJECTION )
diff --git a/src/grid_proj.c b/src/grid_proj.c
new file mode 100644
index 0000000..9868a31
--- /dev/null
+++ b/src/grid_proj.c
@@ -0,0 +1,477 @@
+/*
+  This file is part of CDO. CDO is a collection of Operators to
+  manipulate and analyse Climate model Data.
+
+  Copyright (C) 2003-2017 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
+  See COPYING file for copying and redistribution conditions.
+
+  This program 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; version 2 of the License.
+  This program 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.
+*/
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#if defined(_OPENMP)
+#include <omp.h>
+#endif
+
+#if defined(HAVE_LIBPROJ)
+#include "proj_api.h"
+#endif
+
+#include <stdio.h>
+#include <stdarg.h> /* va_list */
+
+#include <cdi.h>
+#include "cdo_int.h"
+#include "grid.h"
+#include "grid_proj.h"
+
+
+
+static
+char *gen_param(const char *fmt, ...)
+{
+  va_list args;
+  char str[256];
+
+  va_start(args, fmt);
+
+  int len = vsprintf(str, fmt, args);
+
+  va_end(args);
+
+  len++;
+  char *rstr = (char*) Malloc(len*sizeof(char));
+  memcpy(rstr, str, len*sizeof(char));
+
+  return rstr;
+}
+
+static
+void verify_lcc_parameter(double missval, double lon_0, double lat_0, double lat_1, double lat_2, double a, double rf, double x_0, double y_0)
+{
+  const char *projection = "lambert_conformal_conic";
+
+  if ( IS_NOT_EQUAL(a, grid_missval)  && a > 1.e10 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "earth_radius");
+  if ( IS_NOT_EQUAL(rf, grid_missval) && rf > 0 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "inverse_flattening");
+  if ( lon_0 < -360 || lon_0 > 360 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "longitude_of_central_meridian");
+  if ( lat_0 < -90 || lat_0 > 90 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "latitude_of_central_meridian");
+  if ( lat_1 < -90 || lat_1 > 90 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "standard_parallel");
+  if ( lat_2 < -90 || lat_2 > 90 ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "standard_parallel");
+  if ( IS_NOT_EQUAL(x_0, grid_missval) && (x_0 < -1.e20 || x_0 > 1.e20) ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "false_easting");
+  if ( IS_NOT_EQUAL(y_0, grid_missval) && (y_0 < -1.e20 || y_0 > 1.e20) ) cdoWarning("%s mapping parameter %s out of bounds!", projection, "false_northing");
+}
+
+
+int proj_lonlat_to_lcc(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                       double a, double rf, size_t nvals, double *xvals, double *yvals)
+{
+  int status = 0;
+#if defined(HAVE_LIBPROJ)
+  char *params[20];
+
+  int nbpar = 0;
+  params[nbpar++] = gen_param("proj=lcc");
+  if ( IS_NOT_EQUAL(a, missval) && a > 0 ) params[nbpar++] = gen_param("a=%g", a);
+  if ( IS_NOT_EQUAL(rf, missval) && rf > 0 ) params[nbpar++] = gen_param("rf=%g", rf);
+  params[nbpar++] = gen_param("lon_0=%g", lon_0);
+  params[nbpar++] = gen_param("lat_0=%g", lat_0);
+  params[nbpar++] = gen_param("lat_1=%g", lat_1);
+  params[nbpar++] = gen_param("lat_2=%g", lat_2);
+  params[nbpar++] = gen_param("units=m");
+  //  params[nbpar++] = gen_param("no_defs");
+
+  if ( cdoVerbose )
+    for ( int i = 0; i < nbpar; ++i )
+      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
+  
+  projPJ proj = pj_init(nbpar, &params[0]);
+  if ( !proj ) status = -1;
+
+  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
+
+  /* proj->over = 1; */		/* allow longitude > 180 */
+
+  if ( status == 0 )
+    {
+      projUV p;
+      for ( size_t i = 0; i < nvals; i++ )
+        {
+          p.u = xvals[i]*DEG_TO_RAD;
+          p.v = yvals[i]*DEG_TO_RAD;
+          p = pj_fwd(p, proj);
+          xvals[i] = p.u;
+          yvals[i] = p.v;
+        }
+
+      pj_free(proj);
+    }
+#else
+  status = -1;
+#endif
+
+  if ( status == -1 )
+    for ( size_t i = 0; i < nvals; i++ )
+      {
+        xvals[i] = missval;
+        yvals[i] = missval;
+      }
+
+  return status;
+}
+
+static
+void lonlat_to_lcc(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                   double a, double rf, size_t nvals, double *xvals, double *yvals)
+{
+  int status = proj_lonlat_to_lcc(missval, lon_0, lat_0, lat_1, lat_2, a, rf, nvals, xvals, yvals);
+#if defined(HAVE_LIBPROJ)
+  if ( status == -1 ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
+#else
+  if ( status == -1 ) cdoAbort("proj4 support not compiled in!");
+#endif
+}
+
+
+int cdo_lonlat_to_lcc(int gridID, size_t nvals, double *xvals, double *yvals)
+{
+  double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+  gridInqParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+
+  lonlat_to_lcc(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, nvals, xvals, yvals);
+
+  return 0;
+}
+
+
+int proj_lcc_to_lonlat(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                       double a, double rf, double x_0, double y_0, size_t nvals, double *xvals, double *yvals)
+{
+  int status = 0;
+#if defined(HAVE_LIBPROJ)
+  char *params[20];
+
+  int nbpar = 0;
+  params[nbpar++] = gen_param("proj=lcc");
+  if ( IS_NOT_EQUAL(a, grid_missval)  && a  > 0 ) params[nbpar++] = gen_param("a=%g", a);
+  if ( IS_NOT_EQUAL(rf, grid_missval) && rf > 0 ) params[nbpar++] = gen_param("rf=%g", rf);
+  params[nbpar++] = gen_param("lon_0=%g", lon_0);
+  params[nbpar++] = gen_param("lat_0=%g", lat_0);
+  params[nbpar++] = gen_param("lat_1=%g", lat_1);
+  params[nbpar++] = gen_param("lat_2=%g", lat_2);
+  if ( IS_NOT_EQUAL(x_0, grid_missval) ) params[nbpar++] = gen_param("x_0=%g", x_0);
+  if ( IS_NOT_EQUAL(y_0, grid_missval) ) params[nbpar++] = gen_param("y_0=%g", y_0);
+
+  if ( cdoVerbose )
+    for ( int i = 0; i < nbpar; ++i )
+      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
+  
+  projPJ proj = pj_init(nbpar, &params[0]);
+  if ( !proj ) status = -1;
+
+  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
+
+  /* proj->over = 1; */		/* allow longitude > 180 */
+  
+  if ( status == 0 )
+    {
+      projUV p;
+      for ( size_t i = 0; i < nvals; i++ )
+        {
+          p.u = xvals[i];
+          p.v = yvals[i];
+          p = pj_inv(p, proj);
+          xvals[i] = p.u*RAD_TO_DEG;
+          yvals[i] = p.v*RAD_TO_DEG;
+        }
+
+      pj_free(proj);
+    }
+#else
+  status = -1;
+#endif
+
+  if ( status == -1 )
+    for ( size_t i = 0; i < nvals; i++ )
+      {
+        xvals[i] = missval;
+        yvals[i] = missval;
+      }
+
+  return status;
+}
+
+static
+void lcc_to_lonlat(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                   double a, double rf, double x_0, double y_0, size_t nvals, double *xvals, double *yvals)
+{
+  int status = proj_lcc_to_lonlat(missval, lon_0, lat_0, lat_1, lat_2, a, rf, x_0, y_0, nvals, xvals, yvals);
+#if defined(HAVE_LIBPROJ)
+  if ( status == -1 ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
+#else
+  if ( status == -1 ) cdoAbort("proj4 support not compiled in!");
+#endif
+}
+
+
+int cdo_lcc_to_lonlat(int gridID, size_t nvals, double *xvals, double *yvals)
+{
+  const char *projection = "lambert_conformal_conic";
+
+  double lon_0, lat_0, lat_1, lat_2, a, rf, xval_0, yval_0, x_0, y_0;
+  gridInqParamLCC(gridID, grid_missval, &lon_0, &lat_0, &lat_1, &lat_2, &a, &rf, &xval_0, &yval_0, &x_0, &y_0);
+
+  int status = 0;
+  if ( !status && IS_EQUAL(lon_0, grid_missval) ) { status = 1; cdoWarning("%s mapping parameter %s missing!", projection, "longitude_of_central_meridian"); }
+  if ( !status && IS_EQUAL(lat_0, grid_missval) ) { status = 1; cdoWarning("%s mapping parameter %s missing!", projection, "latitude_of_central_meridian"); }
+  if ( !status && IS_EQUAL(lat_1, grid_missval) ) { status = 1; cdoWarning("%s mapping parameter %s missing!", projection, "standard_parallel"); }
+  if ( !status && IS_EQUAL(x_0, grid_missval) && IS_EQUAL(y_0, grid_missval) && IS_NOT_EQUAL(xval_0, grid_missval) && IS_NOT_EQUAL(yval_0, grid_missval) )
+    {
+#if defined(HAVE_LIBPROJ)
+      x_0 = xval_0; y_0 = yval_0;
+      lonlat_to_lcc(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, 1, &x_0, &y_0);
+      x_0 = -x_0; y_0 = -y_0;
+#else
+      status = 1; cdoWarning("%s mapping parameter %s missing!", projection, "false_easting and false_northing");
+#endif
+    }
+
+  if ( status ) cdoAbort("%s mapping parameter missing!", projection);
+
+  verify_lcc_parameter(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, x_0, y_0);
+
+  lcc_to_lonlat(grid_missval, lon_0, lat_0, lat_1, lat_2, a, rf, x_0, y_0, nvals, xvals, yvals);
+
+  return 0;
+}
+
+
+void grid_def_param_sinu(int gridID)
+{
+  const char *projection = "sinusoidal";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, (int)strlen(projection)+1, projection);
+  const char *mapvarname = "Sinusoidal";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, (int)strlen(mapvarname)+1, mapvarname);
+
+  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", (int)strlen(projection), projection);
+}
+
+
+void grid_def_param_laea(int gridID, double a, double lon_0, double lat_0)
+{
+  const char *projection = "lambert_azimuthal_equal_area";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPNAME, (int)strlen(projection)+1, projection);
+  const char *mapvarname = "Lambert_AEA";
+  cdiGridDefKeyStr(gridID, CDI_KEY_MAPPING, (int)strlen(mapvarname)+1, mapvarname);
+
+  cdiDefAttTxt(gridID, CDI_GLOBAL, "grid_mapping_name", (int)strlen(projection), projection);
+  
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "earth_radius", CDI_DATATYPE_FLT64, 1, &a);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "longitude_of_projection_origin", CDI_DATATYPE_FLT64, 1, &lon_0);
+  cdiDefAttFlt(gridID, CDI_GLOBAL, "latitude_of_projection_origin", CDI_DATATYPE_FLT64, 1, &lat_0);
+}
+
+
+void cdo_sinu_to_lonlat(size_t nvals, double *xvals, double *yvals)
+{
+#if defined(HAVE_LIBPROJ)
+  char *params[20];
+
+  int nbpar = 0;
+  params[nbpar++] = gen_param("proj=sinu");
+  params[nbpar++] = gen_param("ellps=WGS84");
+
+  if ( cdoVerbose )
+    for ( int i = 0; i < nbpar; ++i )
+      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
+
+  projPJ proj = pj_init(nbpar, params);
+  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
+
+  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
+
+  /* proj->over = 1; */		/* allow longitude > 180 */
+
+  projUV p;
+  for ( size_t i = 0; i < nvals; i++ )
+    {
+      p.u = xvals[i];
+      p.v = yvals[i];
+      p = pj_inv(p, proj);
+      xvals[i] = p.u*RAD_TO_DEG;
+      yvals[i] = p.v*RAD_TO_DEG;
+      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
+      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
+    }
+
+  pj_free(proj);
+#else
+  cdoAbort("proj4 support not compiled in!");
+#endif
+}
+
+static
+bool cdiInqAttConvertedToFloat(int gridID, int atttype, const char *attname, int attlen, double *attflt)
+{
+  bool status = true;
+
+  if ( atttype == CDI_DATATYPE_INT32 )
+    {
+      int attint[attlen];
+      cdiInqAttInt(gridID, CDI_GLOBAL, attname, attlen, attint);
+      for ( int i = 0; i < attlen; ++i ) attflt[i] = (double)attint[i];
+    }
+  else if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
+    {
+      cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, attflt);
+    }
+  else
+    {
+      status = false;
+    }
+
+  return status;
+}
+
+static
+void grid_inq_param_laea(int gridID, double *a, double *lon_0, double *lat_0, double *x_0, double *y_0)
+{
+  *a = 0; *lon_0 = 0; *lat_0 = 0, *x_0 = 0, *y_0 = 0;
+
+  int gridtype = gridInqType(gridID);
+  if ( gridtype == GRID_PROJECTION )
+    {
+      const char *projection = "lambert_azimuthal_equal_area";
+      char mapping[CDI_MAX_NAME]; mapping[0] = 0;
+      cdiGridInqKeyStr(gridID, CDI_KEY_MAPNAME, CDI_MAX_NAME, mapping);
+      if ( mapping[0] && strcmp(mapping, projection) == 0 )
+        {
+          int atttype, attlen;
+          char attname[CDI_MAX_NAME+1];
+
+          int natts;
+          cdiInqNatts(gridID, CDI_GLOBAL, &natts);
+
+          for ( int iatt = 0; iatt < natts; ++iatt )
+            {
+              cdiInqAtt(gridID, CDI_GLOBAL, iatt, attname, &atttype, &attlen);
+              if ( attlen != 1 ) continue;
+
+              double attflt;
+              if ( cdiInqAttConvertedToFloat(gridID, atttype, attname, attlen, &attflt) )
+                {
+                  if      ( strcmp(attname, "earth_radius") == 0 )                    *a     = attflt;
+                  else if ( strcmp(attname, "longitude_of_projection_origin") == 0 )  *lon_0 = attflt;
+                  else if ( strcmp(attname, "latitude_of_projection_origin") == 0 )   *lat_0 = attflt;
+                  else if ( strcmp(attname, "false_easting")  == 0 )                  *x_0   = attflt;
+                  else if ( strcmp(attname, "false_northing") == 0 )                  *y_0   = attflt;
+                }
+            }
+        }
+      else
+        cdoWarning("%s mapping parameter missing!", projection);
+    }
+}
+
+
+void cdo_laea_to_lonlat(int gridID, size_t nvals, double *xvals, double *yvals)
+{
+#if defined(HAVE_LIBPROJ)
+  char *params[20];
+  
+  double a, lon_0, lat_0, x_0, y_0;
+  grid_inq_param_laea(gridID, &a, &lon_0, &lat_0, &x_0, &y_0);
+
+  int nbpar = 0;
+  params[nbpar++] = gen_param("proj=laea");
+  if ( a > 0 ) params[nbpar++] = gen_param("a=%g", a);
+  params[nbpar++] = gen_param("lon_0=%g", lon_0);
+  params[nbpar++] = gen_param("lat_0=%g", lat_0);
+  if ( IS_NOT_EQUAL(x_0,0) ) params[nbpar++] = gen_param("x_0=%g", x_0);
+  if ( IS_NOT_EQUAL(y_0,0) ) params[nbpar++] = gen_param("y_0=%g", y_0);
+
+  if ( cdoVerbose )
+    for ( int i = 0; i < nbpar; ++i )
+      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
+
+  projPJ proj = pj_init(nbpar, &params[0]);
+  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
+
+  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
+
+  /* proj->over = 1; */		/* allow longitude > 180 */
+
+  projUV p;
+  for ( size_t i = 0; i < nvals; i++ )
+    {
+      p.u = xvals[i];
+      p.v = yvals[i];
+      p = pj_inv(p, proj);
+      xvals[i] = p.u*RAD_TO_DEG;
+      yvals[i] = p.v*RAD_TO_DEG;
+      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
+      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
+    }
+
+  pj_free(proj);
+#else
+  cdoAbort("proj4 support not compiled in!");
+#endif
+}
+
+
+void cdo_proj_to_lonlat(char *proj4param, size_t nvals, double *xvals, double *yvals)
+{
+#if defined(HAVE_LIBPROJ)
+  char *params[99];
+
+  int nbpar;
+  for ( nbpar = 0; nbpar < 99; ++nbpar )
+    {
+      while ( *proj4param == ' ' || *proj4param == '+' ) proj4param++;
+      if ( *proj4param == 0 ) break;
+      char *cstart = proj4param;
+      while ( *proj4param != ' ' && *proj4param != 0 ) proj4param++;
+      char *cend = proj4param;
+      size_t len = cend - cstart;
+      if ( len <= 0 ) break;
+      bool lend = *cend == 0;
+      if ( !lend ) *cend = 0;
+      params[nbpar] = strdup(cstart);
+      if ( !lend ) *cend = ' ';
+    }
+
+  if ( cdoVerbose )
+    for ( int i = 0; i < nbpar; ++i )
+      cdoPrint("Proj.param[%d] = %s", i+1, params[i]);
+
+  projPJ proj = pj_init(nbpar, &params[0]);
+  if ( !proj ) cdoAbort("proj error: %s", pj_strerrno(pj_errno));
+
+  for ( int i = 0; i < nbpar; ++i ) Free(params[i]);
+
+  projUV p;
+  for ( size_t i = 0; i < nvals; i++ )
+    {
+      p.u = xvals[i];
+      p.v = yvals[i];
+      p = pj_inv(p, proj);
+      xvals[i] = p.u*RAD_TO_DEG;
+      yvals[i] = p.v*RAD_TO_DEG;
+      if ( xvals[i] < -9000. || xvals[i] > 9000. ) xvals[i] = -9999.;
+      if ( yvals[i] < -9000. || yvals[i] > 9000. ) yvals[i] = -9999.;
+    }
+
+  pj_free(proj);
+#else
+  cdoAbort("proj4 support not compiled in!");
+#endif
+}
diff --git a/src/grid_proj.h b/src/grid_proj.h
new file mode 100644
index 0000000..9bca934
--- /dev/null
+++ b/src/grid_proj.h
@@ -0,0 +1,24 @@
+#ifndef _GRID_PROJ_H
+#define _GRID_PROJ_H
+
+
+int cdo_lonlat_to_lcc(int gridID, size_t nvals, double *xvals, double *yvals);
+int cdo_lcc_to_lonlat(int gridID, size_t nvals, double *xvals, double *yvals);
+
+void cdo_sinu_to_lonlat(size_t nvals, double *xvals, double *yvals);
+void cdo_laea_to_lonlat(int gridID, size_t nvals, double *xvals, double *yvals);
+
+void cdo_proj_to_lonlat(char *proj4param, size_t nvals, double *xvals, double *yvals);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+int proj_lonlat_to_lcc(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                       double a, double rf, size_t nvals, double *xvals, double *yvals);
+int proj_lcc_to_lonlat(double missval, double lon_0, double lat_0, double lat_1, double lat_2,
+                       double a, double rf, double x_0, double y_0, size_t nvals, double *xvals, double *yvals);
+#if defined (__cplusplus)
+}
+#endif
+
+#endif  /* _GRID_PROJ_H */
diff --git a/src/grid_read.c b/src/grid_read.c
index eb1263d..1af751d 100644
--- a/src/grid_read.c
+++ b/src/grid_read.c
@@ -86,8 +86,6 @@ void grid_read_data(size_t ikv, size_t nkv, kvmap_t *kvmap, griddes_t *grid, siz
           else if ( STR_IS_EQ(gridtype, "cell") )         grid->type = GRID_UNSTRUCTURED;
           else if ( STR_IS_EQ(gridtype, "spectral") )     grid->type = GRID_SPECTRAL;
           else if ( STR_IS_EQ(gridtype, "gme") )          grid->type = GRID_GME;
-          else if ( STR_IS_EQ(gridtype, "lcc") )          grid->type = GRID_LCC;
-          else if ( STR_IS_EQ(gridtype, "lambert") )      grid->type = GRID_LCC;
           else if ( STR_IS_EQ(gridtype, "projection") )   grid->type = GRID_PROJECTION;
           else if ( STR_IS_EQ(gridtype, "generic") )      grid->type = GRID_GENERIC;
 	  else cdoAbort("Invalid gridtype : %s (grid description file: %s)", gridtype, dname);
@@ -108,6 +106,19 @@ void grid_read_data(size_t ikv, size_t nkv, kvmap_t *kvmap, griddes_t *grid, siz
       else if ( STR_IS_EQ(key, "ni") )           { grid->ni = parameter2int(value); grid->nd = 10; }
       else if ( STR_IS_EQ(key, "position") )       grid->position = parameter2int(value);
       else if ( STR_IS_EQ(key, "number") )         grid->number = parameter2int(value);
+      else if ( STR_IS_EQ(key, "scanningMode") )
+        {
+          int scmode = parameter2int(value);
+          if ( (scmode==0) || (scmode==64) || (scmode==96) )
+            {
+              grid->scanningMode = scmode; // -1: not used; allowed modes: <0, 64, 96>; Default is 64
+            }
+          else
+            {
+              cdoWarning("Warning: %d not in allowed modes: <0, 64, 96>; Using default: 64\n", scmode);
+              grid->scanningMode = 64;
+            }
+        }
       else if ( STR_IS_EQ(key, "xname") )     strcpy(grid->xname, parameter2word(value));
       else if ( STR_IS_EQ(key, "yname") )     strcpy(grid->yname, parameter2word(value));
       else if ( STR_IS_EQ(key, "xdimname") )  strcpy(grid->xdimname, parameter2word(value));
@@ -125,21 +136,8 @@ void grid_read_data(size_t ikv, size_t nkv, kvmap_t *kvmap, griddes_t *grid, siz
       else if ( STR_IS_EQ(key, "ylast") )     { grid->ylast = parameter2double(value); grid->def_ylast = true; }
       else if ( STR_IS_EQ(key, "xinc") )      { grid->xinc = parameter2double(value); grid->def_xinc = true; }
       else if ( STR_IS_EQ(key, "yinc") )      { grid->yinc = parameter2double(value); grid->def_yinc = true; }
-      else if ( STR_IS_EQ(key, "originLon") ) { grid->originLon = parameter2double(value); grid->def_originLon = true; }
-      else if ( STR_IS_EQ(key, "originLat") ) { grid->originLat = parameter2double(value); grid->def_originLat = true; }
-      else if ( STR_IS_EQ(key, "lonParY") )   { grid->lonParY = parameter2double(value); grid->def_lonParY = true; }
-      else if ( STR_IS_EQ(key, "lat1") )      { grid->lat1 = parameter2double(value); grid->def_lat1 = true; }
-      else if ( STR_IS_EQ(key, "lat2") )      { grid->lat2 = parameter2double(value); grid->def_lat2 = true; }
-      else if ( STR_IS_EQ(key, "lat_0") )     { grid->lat_0 = parameter2double(value); grid->def_lat_0 = true; }
-      else if ( STR_IS_EQ(key, "lat_1") )     { grid->lat_1 = parameter2double(value); grid->def_lat_1 = true; }
-      else if ( STR_IS_EQ(key, "lat_2") )     { grid->lat_2 = parameter2double(value); grid->def_lat_2 = true; }
-      else if ( STR_IS_EQ(key, "a") )         grid->a = parameter2double(value);
-      else if ( STR_IS_EQ(key, "projection") )
-        {
-          if      ( STR_IS_EQ(value, "north") ) { grid->projflag = 0;    grid->scanflag = 64; }
-	  else if ( STR_IS_EQ(value, "south") ) { grid->projflag = 128;  grid->scanflag = 64; }
-	  else cdoAbort("Invalid projection : %s (grid description file: %s)", value, dname);
-        }
+      else if ( STR_IS_EQ(key, "a") )                 grid->a = parameter2double(value);
+      else if ( STR_IS_EQ(key, "uvRelativeToGrid") )  grid->uvRelativeToGrid = parameter2bool(value);
       else if ( STR_IS_EQ(key, "xvals") )
         {
           size_t size = (grid->type == GRID_CURVILINEAR || grid->type == GRID_UNSTRUCTURED) ? grid->size : grid->xsize;
diff --git a/src/grid_rot.c b/src/grid_rot.c
index 9d707dd..4f40e8f 100644
--- a/src/grid_rot.c
+++ b/src/grid_rot.c
@@ -101,7 +101,7 @@ double phirot_to_phi(double phirot, double lamrot, double polphi, double polgam)
 }
 
 static
-double rl_to_rls(double phi, double rla, double polphi, double pollam)
+double lam_to_lamrot(double phi, double rla, double polphi, double pollam)
 {
   /*
     Umrechnung von rla (geo. System) auf rlas (rot. System)
@@ -131,7 +131,7 @@ double rl_to_rls(double phi, double rla, double polphi, double pollam)
 }
 
 static
-double ph_to_phs(double phi, double rla, double polphi, double pollam)
+double phi_to_phirot(double phi, double rla, double polphi, double pollam)
 {
   /*
     Umrechnung von phi (geo. System) auf phis (rot. System)
@@ -183,7 +183,7 @@ void usvs_to_uv(double us, double vs, double phi, double rla,
   if ( pollamd < 0.0 ) pollamd += 360.0;
 
   /* laenge im rotierten system berechnen */
-  double zrlas = rl_to_rls(phi, rla, polphi, pollam)*DEG2RAD;
+  double zrlas = lam_to_lamrot(phi, rla, polphi, pollam)*DEG2RAD;
 
   /* winkel zbeta berechen (schnittwinkel der breitenkreise) */
   double zarg = - sin(zpolphi)*sin(zrla-zpollam)*sin(zrlas) - cos(zrla-zpollam)*cos(zrlas);
@@ -194,7 +194,7 @@ void usvs_to_uv(double us, double vs, double phi, double rla,
   zbeta = sign(zbeta, -(rla - (pollamd-180.0)));
   */
   double zbeta = fabs(acos(zarg));
-  /*  if ( -(rla - (pollamd-180.0)) < 0 ) zbeta = -zbeta;*/
+  /* if ( -(rla - (pollamd-180.0)) < 0 ) zbeta = -zbeta; */
   if ( (-(rla - (pollamd-180.0)) < 0) && (-(rla - (pollamd-180.0)) >= -180) ) zbeta = -zbeta;
 
   /* us - wind transformieren */
@@ -204,12 +204,12 @@ void usvs_to_uv(double us, double vs, double phi, double rla,
   *v = us*sin(zbeta) + vs*cos(zbeta);
 }
 
-/*
+#ifdef TEST_GRID_ROT
 int main(void)
 {
-  double polphi, pollam;
   double x0, y0, x1, y1, x2, y2;
-  int i;
+  double polphi, pollam;
+  double angle = 0;
 
   polphi = 90.0;
   pollam = 0.0;
@@ -220,25 +220,25 @@ int main(void)
   x0 = -20.0;
   y0 = 0.0;
 
-  for ( i = 0; i < 10; i++ )
+  for ( int i = 0; i < 10; i++ )
     {
       x0 = i *20.0;
-      printf("%g %g\n", x0, y0);
-
-      x1 = rls_to_rl(y0, x0, polphi, pollam);
-      y1 = phs_to_ph(y0, x0, polphi);
+      printf("rot in: %g %g\n", x0, y0);
 
-      printf("%g %g\n", x1, y1);
+      x1 = lamrot_to_lam(y0, x0, polphi, pollam, angle);
+      y1 = phirot_to_phi(y0, x0, polphi, angle);
+      printf("geo: %g %g\n", x1, y1);
 
-      x2 = rl_to_rls(y1, x1, polphi, pollam);
-      y2 = ph_to_phs(y1, x1, polphi, pollam);
-
-      printf("%g %g\n", x2, y2);
+      x2 = lam_to_lamrot(y1, x1, polphi, pollam);
+      y2 = phi_to_phirot(y1, x1, polphi, pollam);
+      printf("rot out:%g %g\n", x2, y2);
     }
 
   usvs_to_uv(30.0, 20.0, 30.0, 0.0, polphi, pollam, &x1, &x2);
-  printf("usvs_to_uv %g %g %g %g\n", polphi, pollam, x1, x2);
+  printf("usvs_to_uv: %g %g %g %g\n", polphi, pollam, x1, x2);
+  printf("usvs_to_uv: 32.5 -170 26.3124 24.6507 <-- reference\n");
 
   return 0;
 }
-*/
+#endif
+
diff --git a/src/griddes.c b/src/griddes.c
index 98e3bf2..1bb6cb1 100644
--- a/src/griddes.c
+++ b/src/griddes.c
@@ -21,7 +21,6 @@
 #include <limits.h>
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "grid.h"
 #include "griddes.h"
@@ -50,30 +49,6 @@ void gridInit(griddes_t *grid)
   grid->ntr           = 0;
   grid->nvertex       = 0;
   grid->genBounds     = false;
-
-  grid->originLon     = 0;
-  grid->originLat     = 0;
-  grid->lonParY       = 0;
-  grid->lat1          = 0;
-  grid->lat2          = 0;
-  grid->projflag      = 0;
-  grid->scanflag      = 64;
-  grid->def_originLon = false;
-  grid->def_originLat = false;
-  grid->def_lonParY   = false;
-  grid->def_lat1      = false;
-  grid->def_lat2      = false;
-
-  grid->a             = 0;
-  grid->lon_0         = 0;
-  grid->lat_0         = 0;
-  grid->lat_1         = 0;
-  grid->lat_2         = 0;
-  grid->def_lon_0     = false;
-  grid->def_lat_0     = false;
-  grid->def_lat_1     = false;
-  grid->def_lat_2     = false;
-
   grid->def_xfirst    = false;
   grid->def_yfirst    = false;
   grid->def_xlast     = false;
@@ -103,6 +78,13 @@ void gridInit(griddes_t *grid)
   grid->xdimname[0]   = 0;
   grid->ydimname[0]   = 0;
   grid->vdimname[0]   = 0;
+  grid->scanningMode  = 64;
+  /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
+               64  = 128 * 0                + 64 *        1         + 32 * 0
+               00  = 128 * 0                + 64 *        0         + 32 * 0
+               96  = 128 * 0                + 64 *        1         + 32 * 1
+     Default / implicit scanning mode is 64:
+                        i and j scan positively, i points are consecutive (row-major)        */
 }
 
 
@@ -143,7 +125,6 @@ int getoptname(char *optname, const char *optstring, int nopt)
 int gridDefine(griddes_t grid)
 {
   int gridID = CDI_UNDEFID;
-  int i;
 
   switch ( grid.type )
     {
@@ -174,6 +155,9 @@ int gridDefine(griddes_t grid)
 
 	gridDefPrec(gridID, grid.prec);
 
+        if ( grid.uvRelativeToGrid ) gridDefUvRelativeToGrid(gridID, 1);
+	if ( grid.nvertex ) gridDefNvertex(gridID, grid.nvertex);
+
 	if ( (grid.def_xfirst || grid.def_xlast || grid.def_xinc) && grid.xvals == NULL )
 	  {
 	    grid.xvals = (double*) Malloc(grid.xsize*sizeof(double));
@@ -183,7 +167,7 @@ int gridDefine(griddes_t grid)
 	      {
 		grid.nvertex = 2;
 		grid.xbounds = (double*) Malloc(grid.xsize*grid.nvertex*sizeof(double));
-		for ( i = 0; i < (int) grid.xsize-1; i++ )
+		for ( int i = 0; i < (int) grid.xsize-1; i++ )
 		  {
 		    grid.xbounds[2*i+1]   = 0.5*(grid.xvals[i] + grid.xvals[i+1]);
 		    grid.xbounds[2*(i+1)] = 0.5*(grid.xvals[i] + grid.xvals[i+1]);
@@ -203,7 +187,7 @@ int gridDefine(griddes_t grid)
 	      {
 		grid.nvertex = 2;
 		grid.ybounds = (double*) Malloc(grid.ysize*grid.nvertex*sizeof(double));
-		for ( i = 0; i < (int) grid.ysize-1; i++ )
+		for ( int i = 0; i < (int) grid.ysize-1; i++ )
 		  {
 		    grid.ybounds[2*i+1]   = 0.5*(grid.yvals[i] + grid.yvals[i+1]);
 		    grid.ybounds[2*(i+1)] = 0.5*(grid.yvals[i] + grid.yvals[i+1]);
@@ -222,38 +206,11 @@ int gridDefine(griddes_t grid)
 	      }
 	  }
 
-	if ( grid.xvals )
-	  {
-	    gridDefXvals(gridID, grid.xvals);
-	    Free(grid.xvals);
-	  }
-
-	if ( grid.yvals )
-	  {
-	    gridDefYvals(gridID, grid.yvals);
-	    Free(grid.yvals);
-	  }
-
-	if ( grid.nvertex )
-	  gridDefNvertex(gridID, grid.nvertex);
-
-	if ( grid.xbounds )
-	  {
-	    gridDefXbounds(gridID, grid.xbounds);
-	    Free(grid.xbounds);
-	  }
-
-	if ( grid.ybounds )
-	  {
-	    gridDefYbounds(gridID, grid.ybounds);
-	    Free(grid.ybounds);
-	  }
-
-	if ( grid.mask )
-	  {
-	    gridDefMask(gridID, grid.mask);
-	    Free(grid.mask);
-	  }
+	if ( grid.xvals )   { gridDefXvals(gridID, grid.xvals); Free(grid.xvals); }
+	if ( grid.yvals )   { gridDefYvals(gridID, grid.yvals); Free(grid.yvals); }
+	if ( grid.xbounds ) { gridDefXbounds(gridID, grid.xbounds); Free(grid.xbounds); }
+	if ( grid.ybounds ) { gridDefYbounds(gridID, grid.ybounds); Free(grid.ybounds); }
+	if ( grid.mask )    { gridDefMask(gridID, grid.mask); Free(grid.mask); }
 
 	break;
       }
@@ -261,12 +218,7 @@ int gridDefine(griddes_t grid)
     case GRID_UNSTRUCTURED:
       {
 	if ( grid.size == 0 )
-	  {
-	    if ( grid.type == GRID_CURVILINEAR )
-	      grid.size = grid.xsize*grid.ysize;
-	    else
-	      grid.size = grid.xsize;
-	  }
+          grid.size = (grid.type == GRID_CURVILINEAR) ? grid.xsize*grid.ysize : grid.xsize;
 
 	gridID = gridCreate(grid.type, grid.size);
 
@@ -290,74 +242,12 @@ int gridDefine(griddes_t grid)
 	    if ( *grid.path ) gridDefReference(gridID, grid.path);
 	  }
 
-	if ( grid.xvals )
-	  {
-	    gridDefXvals(gridID, grid.xvals);
-	    Free(grid.xvals);
-	  }
-
-	if ( grid.yvals )
-	  {
-	    gridDefYvals(gridID, grid.yvals);
-	    Free(grid.yvals);
-	  }
-
-	if ( grid.area )
-	  {
-	    gridDefArea(gridID, grid.area);
-	    Free(grid.area);
-	  }
-
-	if ( grid.xbounds )
-	  {
-	    gridDefXbounds(gridID, grid.xbounds);
-	    Free(grid.xbounds);
-	  }
-
-	if ( grid.ybounds )
-	  {
-	    gridDefYbounds(gridID, grid.ybounds);
-	    Free(grid.ybounds);
-	  }
-
-	if ( grid.mask )
-	  {
-	    gridDefMask(gridID, grid.mask);
-	    Free(grid.mask);
-	  }
-
-	break;
-      }
-    case GRID_LCC:
-      {
-	if ( grid.xsize == 0 ) Error("xsize undefined!");
-	if ( grid.ysize == 0 ) Error("ysize undefined!");
-
-	if ( grid.size == 0 ) grid.size = grid.xsize*grid.ysize;
-
-	gridID = gridCreate(grid.type, grid.size);
-
-	gridDefPrec(gridID, grid.prec);
-
-	gridDefXsize(gridID, grid.xsize);
-	gridDefYsize(gridID, grid.ysize);
-
-	if ( grid.def_originLon == false ) Error("originLon undefined!");
-	if ( grid.def_originLat == false ) Error("originLat undefined!");
-	if ( grid.def_lonParY   == false ) Error("lonParY undefined!");
-	if ( grid.def_lat1      == false ) Error("lat1 undefined!");
-	if ( grid.def_lat2      == false ) Error("lat2 undefined!");
-	if ( grid.def_xinc      == false ) Error("xinc undefined!");
-	if ( grid.def_yinc      == false ) Error("yinc undefined!");
-
-	gridDefParamLCC(gridID, grid.originLon, grid.originLat, grid.lonParY,
-		   grid.lat1, grid.lat2, grid.xinc, grid.yinc, grid.projflag, grid.scanflag);
-
-	if ( grid.mask )
-	  {
-	    gridDefMask(gridID, grid.mask);
-	    Free(grid.mask);
-	  }
+	if ( grid.xvals )   { gridDefXvals(gridID, grid.xvals); Free(grid.xvals); }
+	if ( grid.yvals )   { gridDefYvals(gridID, grid.yvals); Free(grid.yvals); }
+	if ( grid.area )    { gridDefArea(gridID, grid.area); Free(grid.area); }
+	if ( grid.xbounds ) { gridDefXbounds(gridID, grid.xbounds); Free(grid.xbounds); }
+	if ( grid.ybounds ) { gridDefYbounds(gridID, grid.ybounds); Free(grid.ybounds); }
+	if ( grid.mask )    { gridDefMask(gridID, grid.mask); Free(grid.mask); }
 
 	break;
       }
@@ -371,9 +261,7 @@ int gridDefine(griddes_t grid)
 	gridID = gridCreate(grid.type, grid.size);
 
 	gridDefPrec(gridID, grid.prec);
-
 	gridDefTrunc(gridID, grid.ntr);
-
 	gridDefComplexPacking(gridID, grid.lcomplex);
 
 	break;
@@ -387,14 +275,9 @@ int gridDefine(griddes_t grid)
 	gridID = gridCreate(grid.type, grid.size);
 
 	gridDefPrec(gridID, grid.prec);
-
 	gridDefParamGME(gridID, grid.nd, grid.ni, grid.ni2, grid.ni3);
 	
-	if ( grid.mask )
-	  {
-	    gridDefMask(gridID, grid.mask);
-	    Free(grid.mask);
-	  }
+	if ( grid.mask ) { gridDefMask(gridID, grid.mask); Free(grid.mask); }
 
 	break;
       }
diff --git a/src/griddes.h b/src/griddes.h
index 7873dfe..8d62b64 100644
--- a/src/griddes.h
+++ b/src/griddes.h
@@ -14,27 +14,15 @@ typedef struct {
   double  xlast, ylast;
   double  xinc, yinc;
   double  xpole, ypole, angle;    /* rotated north pole             */
-  double  originLon;              /* lambert                        */
-  double  originLat;
-  double  lonParY;
-  double  lat1;
-  double  lat2;
-  int     projflag;
-  int     scanflag;
-  bool    def_originLon;
-  bool    def_originLat;
-  bool    def_lonParY;
-  bool    def_lat1;
-  bool    def_lat2;
+  int     scanningMode;
+  /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
+               64  = 128 * 0                + 64 *        1         + 32 * 0  
+               00  = 128 * 0                + 64 *        0         + 32 * 0
+               96  = 128 * 0                + 64 *        1         + 32 * 1
+     Default / implicit scanning mode is 64:
+                        i and j scan positively, i points are consecutive (row-major)        */
+  bool    uvRelativeToGrid;
   double  a;
-  double  lon_0;
-  double  lat_0;
-  double  lat_1;
-  double  lat_2;
-  bool    def_lon_0;
-  bool    def_lat_0;
-  bool    def_lat_1;
-  bool    def_lat_2;
   int     prec;
   int     isRotated;              /* TRUE for rotated grids         */
   int     type;
diff --git a/src/griddes_h5.c b/src/griddes_h5.c
index f2c6629..5f7ea50 100644
--- a/src/griddes_h5.c
+++ b/src/griddes_h5.c
@@ -9,10 +9,8 @@
 #endif
 
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "griddes.h"
-#include "error.h"
 
 
 #if defined(HAVE_LIBHDF5)
diff --git a/src/griddes_nc.c b/src/griddes_nc.c
index 0f07f5b..0f2eb5f 100644
--- a/src/griddes_nc.c
+++ b/src/griddes_nc.c
@@ -6,21 +6,15 @@
 #  include "netcdf.h"
 #endif
 
-#include <stdio.h>
-
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "griddes.h"
-#include "error.h"
 
 
 #if defined(HAVE_LIBNETCDF)
 static void nce(int istat)
 {
-  /*
-    This routine provides a simple interface to NetCDF error message routine.
-  */
+  // This routine provides a simple interface to NetCDF error message routine.
   if ( istat != NC_NOERR ) cdoAbort(nc_strerror(istat));
 }
 #endif
@@ -100,7 +94,7 @@ int gridFromNCfile(const char *gridfile)
 	{
 	  grid.type = GRID_CURVILINEAR;
 	  if ( grid.nvertex != 4 )
-	    Error("curvilinear grid with %d corners unsupported", grid.nvertex);
+	    cdoAbort("curvilinear grid with %d corners unsupported", grid.nvertex);
 
 	  grid.xsize = grid_dims[0];
 	  grid.ysize = grid_dims[1];
@@ -331,6 +325,6 @@ void writeNCgrid(const char *gridfile, int gridID, int *grid_imask)
   nce(nc_close(nc_file_id));
 
 #else
-  Error("NetCDF support not compiled in!");
+  cdoAbort("NetCDF support not compiled in!");
 #endif
 }
diff --git a/src/gridreference.c b/src/gridreference.c
index a4ed8e5..a210611 100644
--- a/src/gridreference.c
+++ b/src/gridreference.c
@@ -40,6 +40,7 @@ size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
 #endif
 
 /* code from grid_tools.2 */
+static
 int download_gridfile(const char *restrict uri, const char *restrict basename)
 {
   int rval = 1;
@@ -54,14 +55,14 @@ int download_gridfile(const char *restrict uri, const char *restrict basename)
 #endif
 
   CURLcode ret = curl_global_init(curlflags);
-  if(ret != 0)
+  if ( ret != 0 )
     {
       fprintf(stderr, "ERROR: %s!\n", curl_easy_strerror(ret));
       return -1;
     }
 
   CURL *hd = curl_easy_init();
-  if (hd == NULL)
+  if ( hd == NULL )
     {
       fprintf(stderr, "ERROR: could not get curl handler.\n");
       return -1;
@@ -69,7 +70,7 @@ int download_gridfile(const char *restrict uri, const char *restrict basename)
   else
     {
       FILE *fp = fopen(basename, "w");
-      if (fp == NULL)
+      if ( fp == NULL )
 	{
 	  fprintf(stderr, "ERROR: could not open local output file %s. %s.\n", basename, strerror(errno));
 	  return -1;
@@ -108,7 +109,7 @@ int download_gridfile(const char *restrict uri, const char *restrict basename)
       else
 	{
 	  int status = remove(basename);
-	  if (status == -1) perror(basename);
+	  if ( status == -1 ) perror(basename);
 	  fprintf(stderr, "ERROR: %s. Download %s failed.\n\n", curl_easy_strerror(ret), basename);
 	}
       
@@ -131,13 +132,12 @@ int download_gridfile(const char *restrict uri, const char *restrict basename)
 /*
  * Search for filename.
  */
+static
 int search_file(const char *restrict directory, const char *restrict filename)
 {
 #if defined(HAVE_SYS_STAT_H)
   struct stat buf;
-  int status;
-
-  status = stat(directory, &buf);
+  int status = stat(directory, &buf);
 
   if ( status == 0 )
     {
@@ -157,7 +157,6 @@ int search_file(const char *restrict directory, const char *restrict filename)
 int referenceToGrid(int gridID1)
 {
   int gridID2 = -1;
-  int gridsize;
   char griduri[8912];
   char gridpath[8912];
 
@@ -173,9 +172,6 @@ int referenceToGrid(int gridID1)
   else
     {
       bool lgriduri = true;
-      int status;
-      int streamID;
-      int position;
 
       char *basename = strrchr(griduri, '/');
       if ( basename == NULL )
@@ -193,7 +189,7 @@ int referenceToGrid(int gridID1)
       if ( cdoVerbose ) cdoPrint("Search for horizontal grid file \"%s\"", gridpath);
   
       /* scan local directory for file */
-      status = search_file("./", gridpath);
+      int status = search_file("./", gridpath);
       if ( status != 0 )
 	{
 	  if ( cdoGridSearchDir != NULL)
@@ -201,7 +197,7 @@ int referenceToGrid(int gridID1)
 	      strcpy(gridpath, cdoGridSearchDir);
 	      strcat(gridpath, basename);
 	      if ( cdoVerbose ) cdoPrint("Search for horizontal grid file \"%s\"", gridpath);
-  
+
 	      /* scan directory given by environment variable */
 	      status = search_file(cdoGridSearchDir, gridpath);
 	    }
@@ -221,21 +217,19 @@ int referenceToGrid(int gridID1)
 	{
 	  if ( cdoVerbose ) cdoPrint("Horizontal grid file used: %s", gridpath);
       
-	  gridsize = gridInqSize(gridID1);
+	  int gridsize = gridInqSize(gridID1);
 
 	  // int number = gridInqNumber(gridID1);
-	  position = gridInqPosition(gridID1);
+	  int position = gridInqPosition(gridID1);
 
-	  streamID = streamOpenRead(gridpath);
+	  int streamID = streamOpenRead(gridpath);
 	  if ( streamID < 0 ) cdiOpenError(streamID, "Open failed on horizontal grid file >%s<", gridpath);
 
-	  int vlistID, gridID = -1;
-	  int ngrids;
-	  vlistID = streamInqVlist(streamID);
-	  ngrids = vlistNgrids(vlistID);
+	  int vlistID = streamInqVlist(streamID);
+	  int ngrids = vlistNgrids(vlistID);
 	  if ( position > 0 && position <= ngrids )
 	    {
-	      gridID = vlistGrid(vlistID, position-1);
+	      int gridID = vlistGrid(vlistID, position-1);
 	      if ( gridInqSize(gridID) == gridsize )
 		gridID2 = gridDuplicate(gridID);
 	      else
@@ -245,12 +239,12 @@ int referenceToGrid(int gridID1)
 	    {
 	      for ( int grididx = 0; grididx < ngrids; ++grididx )
 		{
-		  gridID = vlistGrid(vlistID, grididx);
+		  int gridID = vlistGrid(vlistID, grididx);
 		  if ( gridInqSize(gridID) == gridsize )
 		    {
 		      gridID2 = gridDuplicate(gridID);
 		      break;
-			}
+                    }
 		}
 	    }
 	  else
diff --git a/src/institution.c b/src/institution.c
index 93f0f07..ead981d 100644
--- a/src/institution.c
+++ b/src/institution.c
@@ -15,29 +15,19 @@
   GNU General Public License for more details.
 */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
-#include "error.h"
 
-#ifndef UNDEFID
-#define UNDEFID  CDI_UNDEFID
-#endif
 
 static
 int readInstitution(const char *instfile)
 {
-  int instID = UNDEFID;
+  int instID = CDI_UNDEFID;
   char line[1024], *pline;
   int lnr = 0;
   int nvar = 0, maxvar = 4;
   char name[1024], longname[1024];
-  int center = UNDEFID, subcenter = UNDEFID;
+  int center = CDI_UNDEFID, subcenter = CDI_UNDEFID;
 
   FILE *instfp = fopen(instfile, "r");
 
@@ -69,7 +59,7 @@ int readInstitution(const char *instfile)
       if ( nvar == 2 && maxvar == 4 )
 	{
 	  if ( ! isdigit((int) pline[0]) )
-	    Error("wrong format in line %d. Missing subcenter!", lnr);
+	    cdoAbort("wrong format in line %d. Missing subcenter!", lnr);
 
 	  subcenter = atoi(pline);
 	}
@@ -88,7 +78,7 @@ int readInstitution(const char *instfile)
   fclose(instfp);
 
   instID = institutInq(center, subcenter, name, longname);
-  if ( instID == UNDEFID )
+  if ( instID == CDI_UNDEFID )
     instID = institutDef(center, subcenter, name, longname);
 
   return instID;
@@ -100,11 +90,11 @@ void defineInstitution(const char *instarg)
   const char *instname = instarg;
   int instID = readInstitution(instname);
 
-  if ( instID == UNDEFID )
+  if ( instID == CDI_UNDEFID )
     instID = institutInq(0, 0, instname, NULL);
 
-  if ( instID == UNDEFID )
-    Error("institution <%s> not found", instname);
+  if ( instID == CDI_UNDEFID )
+    cdoAbort("institution <%s> not found", instname);
 
   cdoDefaultInstID = instID;
 }
diff --git a/src/listarray.c b/src/listarray.c
index a786402..4d9ba01 100644
--- a/src/listarray.c
+++ b/src/listarray.c
@@ -99,7 +99,7 @@ void lista_set_flt(lista_t *lista, int num, double fval)
 }
 
 
-int listaGetInt(lista_t *lista, int num)
+int lista_get_int(lista_t *lista, int num)
 {
   int ival = ((int *) lista->array)[num];
 
@@ -107,7 +107,7 @@ int listaGetInt(lista_t *lista, int num)
 }
 
 
-double listaGetFlt(lista_t *lista, int num)
+double lista_get_flt(lista_t *lista, int num)
 {
   double fval = ((double *) lista->array)[num];
 
diff --git a/src/listarray.h b/src/listarray.h
index c3c955b..1d1fad1 100644
--- a/src/listarray.h
+++ b/src/listarray.h
@@ -36,8 +36,8 @@ void lista_destroy(lista_t *lista);
 void *lista_dataptr(lista_t *lista);
 void lista_set_int(lista_t *lista, int num, int ival);
 void lista_set_flt(lista_t *lista, int num, double fval);
-int listaGetInt(lista_t *lista, int num);
-double listaGetFlt(lista_t *lista, int num);
+int lista_get_int(lista_t *lista, int num);
+double lista_get_flt(lista_t *lista, int num);
 int args2int_lista(int argc, char **argv, lista_t *lista);
 int args2flt_lista(int argc, char **argv, lista_t *lista);
 
diff --git a/src/modules.c b/src/modules.c
index 20e706e..d6f9754 100644
--- a/src/modules.c
+++ b/src/modules.c
@@ -148,7 +148,7 @@ void *Seascount(void *argument);
 void *Seaspctl(void *argument);
 void *Seasstat(void *argument);
 void *Selbox(void *argument);
-void *Selindex(void *argument);
+void *Selgridcell(void *argument);
 void *Select(void *argument);
 void *Selvar(void *argument);
 void *Seloperator(void *argument);
@@ -279,6 +279,11 @@ void *Magplot(void *argument);
 void *Magvector(void *argument);
 void *Maggraph(void *argument);
 
+// HIRLAM_EXTENSIONS
+void *Selmulti(void *argument);   // "selmulti", "delmulti"
+void *WindTrans(void *argument);  // "uvDestag", "rotuvN", "rotuvNorth", "projuvLatLon"
+void *Samplegrid(void *argument); // "samplegrid", "subgrid"
+
 
 #define  AdisitOperators        {"adisit", "adipot"}
 #define  AfterburnerOperators   {"after"}
@@ -345,7 +350,7 @@ void *Maggraph(void *argument);
 #define  ImportbinaryOperators  {"import_binary"}
 #define  ImportcmsafOperators   {"import_cmsaf"}
 #define  ImportobsOperators     {"import_obs"}
-#define  InfoOperators          {"info", "infop", "infon", "infoc", "map"}
+#define  InfoOperators          {"info", "infop", "infon", "infoc", "xinfon", "map"}
 #define  InputOperators         {"input", "inputsrv", "inputext"}
 #define  IntgridOperators       {"intgridbil", "intpoint", "interpolate", "boxavg", "thinout"}
 #define  IntgridtrajOperators   {"intgridtraj"}
@@ -404,7 +409,7 @@ void *Maggraph(void *argument);
 #define  SeaspctlOperators      {"seaspctl"}
 #define  SeasstatOperators      {"seasmin", "seasmax", "seassum", "seasmean", "seasavg", "seasstd", "seasstd1", "seasvar", "seasvar1"}
 #define  SelboxOperators        {"sellonlatbox", "selindexbox"}
-#define  SelindexOperators      {"selindex"}
+#define  SelgridcellOperators   {"selgridcell", "delgridcell"}
 #define  SelectOperators        {"select", "delete"}
 #define  SelvarOperators        {"selparam", "selcode", "selname", "selstdname", "sellevel", "sellevidx", "selgrid", \
                                  "selzaxis", "selzaxisname", "seltabnum", "delparam", "delcode", "delname", "selltype"}
@@ -416,7 +421,7 @@ void *Maggraph(void *argument);
 #define  SetattributeOperators  {"setattribute"}
 #define  SetboxOperators        {"setclonlatbox", "setcindexbox"}
 #define  SetgattOperators       {"setgatt", "setgatts"}
-#define  SetgridOperators       {"setgrid", "setgridtype", "setgridarea", "setgridmask", "unsetgridmask", "setgridnumber", "setgriduri"}
+#define  SetgridOperators       {"setgrid", "setgridtype", "setgridarea", "setgridmask", "unsetgridmask", "setgridnumber", "setgriduri", "usegridnumber"}
 #define  SethaloOperators       {"sethalo", "tpnhalo"}
 #define  SetmissOperators       {"setmissval", "setctomiss", "setmisstoc", "setrtomiss", "setvrange"}
 #define  SetmisstonnOperators   {"setmisstonn", "setmisstodis"}
@@ -428,7 +433,7 @@ void *Maggraph(void *argument);
 #define  SetzaxisOperators      {"setzaxis", "genlevelbounds"}
 #define  ShiftxyOperators       {"shiftx", "shifty"}
 #define  ShowinfoOperators      {"showyear", "showmon", "showdate", "showtime", "showtimestamp", "showcode", "showunit", \
-                                 "showparam", "showname", "showstdname", "showlevel", "showltype", "showformat"}
+                                 "showparam", "showname", "showstdname", "showlevel", "showltype", "showformat", "showgrid"}
 #define  SinfoOperators         {"sinfo", "sinfop", "sinfon", "sinfoc", "seinfo", "seinfop", "seinfon", "seinfoc"}
 #define  SmoothOperators        {"smooth", "smooth9"}
 #define  SortOperators          {"sortcode", "sortparam", "sortname", "sortlevel"}
@@ -562,6 +567,12 @@ void *Maggraph(void *argument);
 #define  MagvectorOperators     {"vector"}
 #define  MaggraphOperators      {"graph"}
 
+// HIRLAM_EXTENSIONS
+#define  SelmultiOperators      {"selmulti", "delmulti", "changemulti"}
+#define  WindTransOperators     {"uvDestag", "rotuvN", "rotuvNorth", "projuvLatLon"}
+#define  SamplegridOperators    {"samplegrid", "subgrid"}
+
+
 static modules_t Modules[] =
 {
   // stream in  -1 means: unlimited number of input streams
@@ -690,7 +701,7 @@ static modules_t Modules[] =
   { Seaspctl,       SeaspctlHelp,      SeaspctlOperators,      1,   CDI_REAL,  3,  1 },
   { Seasstat,       SeasstatHelp,      SeasstatOperators,      1,   CDI_REAL,  1,  1 },
   { Selbox,         SelboxHelp,        SelboxOperators,        1,   CDI_BOTH,  1,  1 },
-  { Selindex,       NULL,              SelindexOperators,      1,   CDI_BOTH,  1,  1 },
+  { Selgridcell,    SelgridcellHelp,   SelgridcellOperators,   1,   CDI_BOTH,  1,  1 },
   { Select,         SelectHelp,        SelectOperators,        1,   CDI_BOTH, -1,  1 },
   { Selvar,         SelvarHelp,        SelvarOperators,        1,   CDI_BOTH,  1,  1 },
   { Selrec,         SelvarHelp,        SelrecOperators,        1,   CDI_BOTH,  1,  1 },
@@ -831,6 +842,10 @@ static modules_t Modules[] =
   { Magplot,        MagplotHelp,       MagplotOperators,       1,   CDI_REAL,  1,  1 },
   { Magvector,      MagvectorHelp,     MagvectorOperators,     1,   CDI_REAL,  1,  1 },
   { Maggraph,       MaggraphHelp,      MaggraphOperators,      1,   CDI_REAL, -1,  1 },
+  // HIRLAM_EXTENSIONS
+  { Samplegrid,     SamplegridHelp,    SamplegridOperators,    1,   CDI_REAL,  1,  1 },
+  { Selmulti,       SelmultiHelp,      SelmultiOperators,      1,   CDI_REAL,  1,  1 },
+  { WindTrans,      WindTransHelp,     WindTransOperators,     1,   CDI_REAL,  1,  1 },
 };							       
 							       
 static int NumModules = sizeof(Modules) / sizeof(Modules[0]);
@@ -845,8 +860,6 @@ static const char *opalias[][2] =
   {"covar0r",             "fldcovar"},
   {"gather",              "collgrid"},
   {"geopotheight",        "gheight"},
-  {"ggstat",              "info"},
-  {"ggstats",             "sinfo"},
   {"globavg",             "fldavg"},
   {"import_grads",        "import_binary"},
   {"infos",               "sinfo"},
@@ -888,6 +901,8 @@ static const char *opalias[][2] =
   {"outputbounds",        "gmtcells"},
   {"selseas",             "selseason"},
   {"selmon",              "selmonth"},
+  {"selindex",            "selgridcell"},
+  {"delindex",            "delgridcell"},
 };
 
 static int nopalias = sizeof(opalias) / (2*sizeof(opalias[0][0]));
diff --git a/src/namelist.c b/src/namelist.c
index 715599f..ac5e24c 100644
--- a/src/namelist.c
+++ b/src/namelist.c
@@ -110,7 +110,7 @@ int namelist_parse_word(namelist_parser *parser, const char *buf, size_t len)
 
 // Fills next token with NAMELIST string.
 static
-int namelist_parse_string(namelist_parser *parser, const char *buf, size_t len)
+int namelist_parse_string(namelist_parser *parser, const char *buf, size_t len, char quote)
 {
   int start = parser->pos;
 
@@ -122,7 +122,7 @@ int namelist_parse_string(namelist_parser *parser, const char *buf, size_t len)
       char c = buf[parser->pos];
 
       /* Quote: end of string */
-      if ( c == '\"' )
+      if ( c == quote )
         {
           namelisttok_t *token = namelist_alloc_token(parser);
           namelist_fill_token(token, NAMELIST_STRING, start+1, parser->pos);
@@ -238,8 +238,8 @@ int namelist_parse(namelist_parser *parser, const char *buf, size_t len)
         case ':': case '=':
           status = namelist_check_keyname(buf, &parser->tokens[parser->toknext-1]);
           break;
-        case '\"':
-          status = namelist_parse_string(parser, buf, len);
+        case '\"': case '\'':
+          status = namelist_parse_string(parser, buf, len, c);
           break;
         default:
           status = namelist_parse_word(parser, buf, len);
diff --git a/src/namelist_parser.c b/src/namelist_parser.c
index 325a8c5..bf8ff83 100644
--- a/src/namelist_parser.c
+++ b/src/namelist_parser.c
@@ -5,6 +5,7 @@
 static
 void kvlist_append_namelist(list_t *kvlist, const char *key, const char *buffer, namelisttok_t *t, int nvalues)
 {
+  char vbuf[4096];
   keyValues_t *keyval = (keyValues_t *) malloc(sizeof(keyValues_t));
   keyval->key = strdup(key);
   keyval->nvalues = nvalues;
@@ -16,7 +17,14 @@ void kvlist_append_namelist(list_t *kvlist, const char *key, const char *buffer,
       size_t len = t[i].end - t[i].start;
       char *value = (char*) malloc((len+1)*sizeof(char));
       //printf(" value >%.*s<\n", len, buffer+t[i].start);
-      snprintf(value, len+1, "%.*s", (int)len, buffer+t[i].start);
+      const char *pval = buffer+t[i].start;
+      if ( len < sizeof(vbuf) ) // snprintf seems to call strlen(pval)
+        {
+          memcpy(vbuf, buffer+t[i].start, len);
+          vbuf[len] = 0;
+          pval = vbuf;
+        }
+      snprintf(value, len+1, "%.*s", (int)len, pval);
       value[len] = 0;
       keyval->values[i] = value;
     }
diff --git a/src/operator_help.h b/src/operator_help.h
index 50ad2fe..ca20c82 100644
--- a/src/operator_help.h
+++ b/src/operator_help.h
@@ -426,9 +426,9 @@ static const char *DistgridHelp[] = {
     "    distgrid,nx[,ny]  infile obase",
     "",
     "DESCRIPTION",
-    "    This operator distributes a dataset into smaller pieces. Each output file contains a different region of the horizontal ",
-    "    source grid. A target grid region contains a structured longitude/latitude box of the source grid. Only rectilinear and",
-    "    curvilinear source grids are supported by this operator.",
+    "    This operator distributes a dataset into smaller pieces. Each output file contains a different region of the",
+    "    horizontal source grid. A target grid region contains a structured longitude/latitude box of the source grid.",
+    "    Only rectilinear and curvilinear source grids are supported by this operator.",
     "    The number of different regions can be specified with the parameter nx and ny. The output files will be named ",
     "    <obase><xxx><suffix> where suffix is the filename extension derived from the file format. xxx will have five digits with ",
     "    the number of the target region.",
@@ -509,6 +509,57 @@ static const char *SelectHelp[] = {
     "    year              INTEGER Comma separated list of years.",
     "    timestep          INTEGER Comma separated list of timesteps. Negative values selects timesteps from the end (NetCDF only).",
     "    timestep_of_year  INTEGER Comma separated list of timesteps of year.",
+    "    timestepmask      STRING  Read timesteps from a mask file.",
+    NULL
+};
+
+static const char *SelmultiHelp[] = {
+    "NAME",
+    "    selmulti, delmulti, changemulti - Select multiple fields via GRIB1 parameters",
+    "",
+    "SYNOPSIS",
+    "    <operator>,selection-specification  infile outfile",
+    "",
+    "DESCRIPTION",
+    "    This module selects multiple fields from infile and writes them to outfile.",
+    "    selection-specification is a filename or in-place string with the selection specification.",
+    "    Each selection-specification has the following compact notation format: ",
+    "    ",
+    "       <type>(parameters; leveltype(s); levels)",
+    "    ",
+    "    type      "    "    sel for select or del for delete (optional)",
+    "    parameters"    "    GRIB1 parameter code number",
+    "    leveltype "    "    GRIB1 level type",
+    "    levels    "    "    value of each level",
+    "    ",
+    "    Examples:",
+    "    ",
+    "       (1; 103; 0) ",
+    "       (33,34; 105; 10) ",
+    "       (11,17; 105; 2) ",
+    "       (71,73,74,75,61,62,65,117,67,122,121,11,131,66,84,111,112; 105; 0) ",
+    "    ",
+    "    The following descriptive notation can also be used for selection specification from a file:",
+    "    ",
+    "       SELECT/DELETE, PARAMETER=parameters, LEVTYPE=leveltye(s), LEVEL=levels",
+    "    ",
+    "    Examples:",
+    "    ",
+    "       SELECT, PARAMETER=1, LEVTYPE=103, LEVEL=0 ",
+    "       SELECT, PARAMETER=33/34, LEVTYPE=105, LEVEL=10 ",
+    "       SELECT, PARAMETER=11/17, LEVTYPE=105, LEVEL=2 ",
+    "       SELECT, PARAMETER=71/73/74/75/61/62/65/117/67/122, LEVTYPE=105, LEVEL=0 ",
+    "       DELETE, PARAMETER=128, LEVTYPE=109, LEVEL=* ",
+    "    ",
+    "    The following will convert Pressure from Pa into hPa; Temp from Kelvin to Celsius: ",
+    "       SELECT, PARAMETER=1, LEVTYPE= 103, LEVEL=0, SCALE=0.01 ",
+    "       SELECT, PARAMETER=11, LEVTYPE=105, LEVEL=2, OFFSET=273.15 ",
+    "    If SCALE and/or OFFSET are defined, then the data values are scaled as SCALE*(VALUE-OFFSET).",
+    "",
+    "OPERATORS",
+    "    selmulti     Select multiple fields",
+    "    delmulti     Delete multiple fields",
+    "    changemulti  Change identication of multiple fields",
     NULL
 };
 
@@ -645,7 +696,7 @@ static const char *SelboxHelp[] = {
     "    selindexbox,idx1,idx2,idy1,idy2  infile outfile",
     "",
     "DESCRIPTION",
-    "    Selects a box of the rectangularly understood field. All input fields need to have the same horizontal grid.",
+    "    Selects a box of the rectangularly understood field.",
     "",
     "OPERATORS",
     "    sellonlatbox  Select a longitude/latitude box",
@@ -661,10 +712,47 @@ static const char *SelboxHelp[] = {
     "    lon2  FLOAT    Eastern longitude",
     "    lat1  FLOAT    Southern or northern latitude",
     "    lat2  FLOAT    Northern or southern latitude",
-    "    idx1  INTEGER  Index of first longitude",
-    "    idx2  INTEGER  Index of last longitude",
-    "    idy1  INTEGER  Index of first latitude",
-    "    idy2  INTEGER  Index of last latitude",
+    "    idx1  INTEGER  Index of first longitude (1 - nlon)",
+    "    idx2  INTEGER  Index of last longitude (1 - nlon)",
+    "    idy1  INTEGER  Index of first latitude (1 - nlat)",
+    "    idy2  INTEGER  Index of last latitude (1 - nlat)",
+    NULL
+};
+
+static const char *SelgridcellHelp[] = {
+    "NAME",
+    "    selgridcell, delgridcell - Select grid cells",
+    "",
+    "SYNOPSIS",
+    "    <operator>,indexes  infile outfile",
+    "",
+    "DESCRIPTION",
+    "    Selects grid cells of all fields from infile. The user has to give the indexes of each",
+    "    grid cell. The resulting grid in outfile is unstructured.",
+    "",
+    "OPERATORS",
+    "    selgridcell  Select grid cells",
+    "    delgridcell  Delete grid cells",
+    "",
+    "PARAMETER",
+    "    indexes  INTEGER  Comma separated list of indexes",
+    NULL
+};
+
+static const char *SamplegridHelp[] = {
+    "NAME",
+    "    samplegrid - Resample grid",
+    "",
+    "SYNOPSIS",
+    "    samplegrid,factor  infile outfile",
+    "",
+    "DESCRIPTION",
+    "    This is a special operator for resampling the horizontal grid.",
+    "    No interpolation takes place. Resample factor=2 means every second grid point is removed.",
+    "    Only rectilinear and curvilinear source grids are supported by this operator.",
+    "",
+    "PARAMETER",
+    "    factor  INTEGER  Resample factor, typically 2, which will half the resolution",
     NULL
 };
 
@@ -3931,7 +4019,7 @@ static const char *VertintmlHelp[] = {
     "           Interpolates 3D variables on hybrid sigma pressure level to pressure level.",
     "    ml2hl  Model to height level interpolation",
     "           Interpolates 3D variables on hybrid sigma pressure level to height level.",
-    "           The procedure is the same as for the operator mh2pl except for",
+    "           The procedure is the same as for the operator ml2pl except for",
     "           the pressure levels being calculated from the heights by:",
     "           plevel = 101325*exp(hlevel/-7000)",
     "",
@@ -4748,6 +4836,37 @@ static const char *VargenHelp[] = {
     NULL
 };
 
+static const char *WindTransHelp[] = {
+    "NAME",
+    "    uvDestag, rotuvNorth, projuvLatLon - Wind Transformation",
+    "",
+    "SYNOPSIS",
+    "    uvDestag,u,v[,-/+0.5[,-/+0.5]]  infile outfile",
+    "    rotuvNorth,u,v  infile outfile",
+    "    projuvLatLon,u,v  infile outfile",
+    "",
+    "DESCRIPTION",
+    "    This module contains special operators for datsets with wind components on a rotated lon/lat grid, ",
+    "    e.g. data from the regional model HIRLAM or REMO. ",
+    "",
+    "OPERATORS",
+    "    uvDestag      Destaggering of u/v wind components",
+    "                  This is a special operator for destaggering of wind components.",
+    "                  If the file contains a grid with temperature (name='t' or code=11)",
+    "                  then grid_temp will be used for destaggered wind.",
+    "    rotuvNorth    Rotate u/v wind to North pole.",
+    "                  This is an operator for transformation of wind-vectors from grid-relative to north-pole",
+    "                  relative for the whole file. (FAST implementation with JACOBIANS)",
+    "    projuvLatLon  Cylindrical Equidistant projection",
+    "                  Thus is an operator for transformation of wind-vectors from the globe-spherical coordinate system",
+    "                  into a flat Cylindrical Equidistant (lat-lon) projection. (FAST JACOBIAN implementation)",
+    "",
+    "PARAMETER",
+    "    u,v            STRING  Pair of u,v wind components (use variable names or code numbers)",
+    "    -/+0.5,-/+0.5  STRING  Destaggered grid offsets are optional (default -0.5,-0.5)",
+    NULL
+};
+
 static const char *RotuvbHelp[] = {
     "NAME",
     "    rotuvb - Rotation",
diff --git a/src/printinfo.h b/src/printinfo.h
index bdde1cc..e0fe4b4 100644
--- a/src/printinfo.h
+++ b/src/printinfo.h
@@ -226,7 +226,7 @@ void print_xyvals2D(int gridID, int dig)
           int xsize = gridInqXsize(gridID);
           if ( xsize > 1 )
             {
-              double *xvals = (double*) malloc(xsize*sizeof(double));
+              double *xvals = (double*) malloc((size_t)xsize*sizeof(double));
               for ( int i = 0; i < xsize; ++i ) xvals[i] = xvals2D[i];
               xinc = fabs(xvals[xsize-1] - xvals[0])/(xsize-1);
               for ( int i = 2; i < xsize; i++ )
@@ -236,7 +236,7 @@ void print_xyvals2D(int gridID, int dig)
           int ysize = gridInqYsize(gridID);
           if ( ysize > 1 )
             {
-              double *yvals = (double*) malloc(ysize*sizeof(double));
+              double *yvals = (double*) malloc((size_t)ysize*sizeof(double));
               for ( int i = 0; i < ysize; ++i ) yvals[i] = yvals2D[i*xsize];
               yinc = fabs(yvals[ysize-1] - yvals[0])/(ysize-1);
               for ( int i = 2; i < ysize; i++ )
@@ -410,27 +410,6 @@ void printGridInfoKernel(int gridID, int index, bool lproj)
 
       print_xyvals2D(gridID, dig);
     }
-  else if ( gridtype == GRID_LCC )
-    {
-      double originLon, originLat, lonParY, lat1, lat2, xincm, yincm;
-      int projflag, scanflag;
-
-      gridInqParamLCC(gridID, &originLon, &originLat, &lonParY, &lat1, &lat2, &xincm, &yincm,
-                 &projflag, &scanflag);
-
-#ifdef CDO
-      set_text_color(stdout, RESET, GREEN);
-#endif
-      fprintf(stdout, "points=%d (%dx%d)  ", gridsize, xsize, ysize);
-      if ( (projflag&128) == 0 )
-        fprintf(stdout, "North Pole\n");
-      else
-        fprintf(stdout, "South Pole\n");
-      my_reset_text_color(stdout);
-
-      fprintf(stdout, "%33s : originLon=%g  originLat=%g  lonParY=%g\n", " ", originLon, originLat, lonParY);
-      fprintf(stdout, "%33s : lat1=%g  lat2=%g  xinc=%g m  yinc=%g m\n", " ", lat1, lat2, xincm, yincm);
-    }
   else /* if ( gridtype == GRID_GENERIC ) */
     {
 #ifdef CDO
@@ -443,7 +422,7 @@ void printGridInfoKernel(int gridID, int index, bool lproj)
       my_reset_text_color(stdout);
     }
 
-  if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED || gridtype == GRID_LCC )
+  if ( gridtype == GRID_CURVILINEAR || gridtype == GRID_UNSTRUCTURED )
     {
       if ( gridHasArea(gridID) ||
            gridInqXbounds(gridID, NULL) || gridInqYbounds(gridID, NULL) )
diff --git a/src/remap_bilinear_scrip.c b/src/remap_bilinear_scrip.c
index 425bc2e..8aa436b 100644
--- a/src/remap_bilinear_scrip.c
+++ b/src/remap_bilinear_scrip.c
@@ -16,10 +16,7 @@ int find_ij_weights(double plon, double plat, double *restrict src_lats, double
 {
   int lfound = 0;
   long iter;                     /*  iteration counters   */
-  double iguess, jguess;         /*  current guess for bilinear coordinate  */
   double deli, delj;             /*  corrections to iw,jw                   */
-  double dth1, dth2, dth3;       /*  some latitude  differences             */
-  double dph1, dph2, dph3;       /*  some longitude differences             */
   double dthp, dphp;             /*  difference between point and sw corner */
   double mat1, mat2, mat3, mat4; /*  matrix elements                        */
   double determinant;            /*  matrix determinant                     */
@@ -28,13 +25,15 @@ int find_ij_weights(double plon, double plat, double *restrict src_lats, double
 
   /* Iterate to find iw,jw for bilinear approximation  */
 
-  dth1 = src_lats[1] - src_lats[0];
-  dth2 = src_lats[3] - src_lats[0];
-  dth3 = src_lats[2] - src_lats[1] - dth2;
+  // some latitude  differences 
+  double dth1 = src_lats[1] - src_lats[0];
+  double dth2 = src_lats[3] - src_lats[0];
+  double dth3 = src_lats[2] - src_lats[1] - dth2;
 
-  dph1 = src_lons[1] - src_lons[0];
-  dph2 = src_lons[3] - src_lons[0];
-  dph3 = src_lons[2] - src_lons[1];
+  // some longitude differences
+  double dph1 = src_lons[1] - src_lons[0];
+  double dph2 = src_lons[3] - src_lons[0];
+  double dph3 = src_lons[2] - src_lons[1];
 
   if ( dph1 >  THREE*PIH ) dph1 -= PI2;
   if ( dph2 >  THREE*PIH ) dph2 -= PI2;
@@ -45,8 +44,9 @@ int find_ij_weights(double plon, double plat, double *restrict src_lats, double
 
   dph3 = dph3 - dph2;
 
-  iguess = HALF;
-  jguess = HALF;
+  // current guess for bilinear coordinate
+  double iguess = HALF;
+  double jguess = HALF;
 
   for ( iter = 0; iter < remap_max_iter; ++iter )
     {
@@ -110,17 +110,16 @@ int num_src_points(const int* restrict mask, const int src_add[4], double src_la
 static
 void renormalize_weights(const double src_lats[4], double wgts[4])
 {
-  int n;
   double sum_wgts = 0.0; /* sum of weights for normalization */
   /* 2012-05-08 Uwe Schulzweida: using absolute value of src_lats (bug fix) */
-  for ( n = 0; n < 4; ++n ) sum_wgts += fabs(src_lats[n]);
-  for ( n = 0; n < 4; ++n ) wgts[n] = fabs(src_lats[n])/sum_wgts;
+  for ( int n = 0; n < 4; ++n ) sum_wgts += fabs(src_lats[n]);
+  for ( int n = 0; n < 4; ++n ) wgts[n] = fabs(src_lats[n])/sum_wgts;
 }
 
 static
 void bilinear_warning(double plon, double plat, double iw, double jw, int* src_add, double* src_lons, double* src_lats, remapgrid_t* src_grid)
 {
-  static int lwarn = TRUE;
+  static bool lwarn = true;
 
   if ( cdoVerbose )
     {
@@ -139,7 +138,7 @@ void bilinear_warning(double plon, double plat, double iw, double jw, int* src_a
 
   if ( cdoVerbose || lwarn )
     {
-      lwarn = FALSE;
+      lwarn = false;
       //  cdoWarning("Iteration for iw,jw exceed max iteration count of %d!", remap_max_iter);
       cdoWarning("Bilinear interpolation failed for some grid points - used a distance-weighted average instead!");
     }
diff --git a/src/remap_distwgt.c b/src/remap_distwgt.c
index 0791afc..c2546b5 100644
--- a/src/remap_distwgt.c
+++ b/src/remap_distwgt.c
@@ -24,12 +24,11 @@ void nbr_store_distance(int nadd, double distance, int num_neighbors, int *restr
     }
   else
     {
-      int n, nchk;
-      for ( nchk = 0; nchk < num_neighbors; ++nchk )
+      for ( int nchk = 0; nchk < num_neighbors; ++nchk )
 	{
 	  if ( distance < nbr_dist[nchk] || (distance <= nbr_dist[nchk] && nadd < nbr_add[nchk]) )
 	    {
-	      for ( n = num_neighbors-1; n > nchk; --n )
+	      for ( int n = num_neighbors-1; n > nchk; --n )
 		{
 		  nbr_add[n]  = nbr_add[n-1];
 		  nbr_dist[n] = nbr_dist[n-1];
@@ -51,7 +50,7 @@ void nbr_check_distance(unsigned num_neighbors, const int *restrict nbr_add, dou
 }
 
 
-double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, int *restrict nbr_mask, const int *restrict nbr_add, double *restrict nbr_dist)
+double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_mask, bool *restrict nbr_mask, const int *restrict nbr_add, double *restrict nbr_dist)
 {
   // Compute weights based on inverse distance if mask is false, eliminate those points
 
@@ -61,13 +60,13 @@ double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_
     {
       for ( unsigned n = 0; n < num_neighbors; ++n )
         {
-          nbr_mask[n] = FALSE;
+          nbr_mask[n] = false;
           if ( nbr_add[n] >= 0 )
             if ( src_grid_mask[nbr_add[n]] )
               {
                 nbr_dist[n] = 1./nbr_dist[n];
                 dist_tot += nbr_dist[n];
-                nbr_mask[n] = TRUE;
+                nbr_mask[n] = true;
               }
         }
     }
@@ -75,12 +74,12 @@ double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_
     {
       for ( unsigned n = 0; n < num_neighbors; ++n )
         {
-          nbr_mask[n] = FALSE;
+          nbr_mask[n] = false;
           if ( nbr_add[n] >= 0 )
             {
               nbr_dist[n] = 1./nbr_dist[n];
               dist_tot += nbr_dist[n];
-              nbr_mask[n] = TRUE;
+              nbr_mask[n] = true;
             }
         }
     }
@@ -89,7 +88,7 @@ double nbr_compute_weights(unsigned num_neighbors, const int *restrict src_grid_
 }
 
 
-unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const int *restrict nbr_mask, int *restrict nbr_add, double *restrict nbr_dist)
+unsigned nbr_normalize_weights(unsigned num_neighbors, double dist_tot, const bool *restrict nbr_mask, int *restrict nbr_add, double *restrict nbr_dist)
 {
   // Normalize weights and store the link
 
@@ -127,7 +126,6 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
     double plat,         ! latitude  of the search point
     double plon,         ! longitude of the search point
   */
-  int lfound;
   int n, nadd;
   long ii, jj;
   int i, j, ix;
@@ -157,7 +155,7 @@ void grid_search_nbr_reg2d(struct gridsearch *gs, int num_neighbors, remapgrid_t
   if ( plon < src_center_lon[0]     ) plon += PI2;
   if ( plon > src_center_lon[nxm-1] ) plon -= PI2;
 
-  lfound = rect_grid_search(&ii, &jj, plon, plat, nxm, ny, src_center_lon, src_center_lat);
+  int lfound = rect_grid_search(&ii, &jj, plon, plat, nxm, ny, src_center_lon, src_center_lat);
 
   if ( lfound )
     {
@@ -381,7 +379,7 @@ void remap_distwgt_weights(unsigned num_neighbors, remapgrid_t *src_grid, remapg
   for ( unsigned tgt_cell_add = 1; tgt_cell_add < tgt_grid_size; ++tgt_cell_add )
     weightlinks[tgt_cell_add].addweights = weightlinks[0].addweights + num_neighbors*tgt_cell_add;
 
-  int nbr_mask[num_neighbors];    // mask at nearest neighbors
+  bool nbr_mask[num_neighbors];   // mask at nearest neighbors
   int nbr_add[num_neighbors];     // source address at nearest neighbors
   double nbr_dist[num_neighbors]; // angular distance four nearest neighbors
 
@@ -484,7 +482,7 @@ void remap_distwgt(unsigned num_neighbors, remapgrid_t *src_grid, remapgrid_t *t
   unsigned ny = src_grid->dims[1];
   bool lcyclic = src_grid->is_cyclic;
 
-  int nbr_mask[num_neighbors];    // mask at nearest neighbors
+  bool nbr_mask[num_neighbors];   // mask at nearest neighbors
   int nbr_add[num_neighbors];     // source address at nearest neighbors
   double nbr_dist[num_neighbors]; // angular distance four nearest neighbors
 
diff --git a/src/remap_search_latbins.c b/src/remap_search_latbins.c
index c1bb18c..90cc906 100644
--- a/src/remap_search_latbins.c
+++ b/src/remap_search_latbins.c
@@ -1,4 +1,5 @@
 #include "cdo_int.h"
+#include "grid.h"
 #include "remap.h"
 /*
 #if defined(_OPENMP)
@@ -293,7 +294,7 @@ int grid_search_nn(long min_add, long max_add, int *restrict nbr_add, double *re
   for ( n = 0; n < 4; ++n ) distance += nbr_dist[n];
   for ( n = 0; n < 4; ++n ) nbr_dist[n] /= distance;
 
-  return (search_result);
+  return search_result;
 }
 
 
@@ -325,31 +326,27 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
   */
   /*  Local variables */
   long n, n2, next_n, srch_add, srch_add4;    /* dummy indices                    */
-  long nx, ny;                                /* dimensions of src grid           */
-  long min_add, max_add;                      /* addresses for restricting search */
-  long i, j, jp1, ip1, n_add, e_add, ne_add;  /* addresses                        */
-  long nbins;
   /* Vectors for cross-product check */
   double vec1_lat, vec1_lon;
-  double vec2_lat, vec2_lon, cross_product;
+  double vec2_lat, vec2_lon;
   int scross[4], scross_last = 0;
   int search_result = 0;
-  restr_t rlat, rlon;
   restr_t *bin_lats = src_grid->bin_lats;
 
-  nbins = src_grid->num_srch_bins;
+  long nbins = src_grid->num_srch_bins;
 
-  rlat = RESTR_SCALE(plat);
-  rlon = RESTR_SCALE(plon);
+  restr_t rlat = RESTR_SCALE(plat);
+  restr_t rlon = RESTR_SCALE(plon);
 
-  /* restrict search first using bins */
+  // restrict search first using bins
 
   for ( n = 0; n < 4; ++n ) src_add[n] = 0;
 
-  min_add = src_grid->size-1;
-  max_add = 0;
+  // addresses for restricting search
+  long min_add = src_grid->size-1;
+  long max_add = 0;
 
-  for ( n = 0; n < nbins; ++n )
+  for ( long  n = 0; n < nbins; ++n )
     {
       n2 = n<<1;
       if ( rlat >= bin_lats[n2] && rlat <= bin_lats[n2+1] )
@@ -361,8 +358,8 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
  
   /* Now perform a more detailed search */
 
-  nx = src_grid_dims[0];
-  ny = src_grid_dims[1];
+  long nx = src_grid_dims[0];
+  long ny = src_grid_dims[1];
 
   /* srch_loop */
   for ( srch_add = min_add; srch_add <= max_add; ++srch_add )
@@ -377,31 +374,15 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
 	  /* We are within bounding box so get really serious */
 
           /* Determine neighbor addresses */
-          j = srch_add/nx;
-          i = srch_add - j*nx;
-
-          if ( i < (nx-1) )
-            ip1 = i + 1;
-          else
-	    {
-	      /* 2009-01-09 Uwe Schulzweida: bug fix */
-	      if ( src_grid->is_cyclic )
-		ip1 = 0;
-	      else
-		ip1 = i;
-	    }
+          long j = srch_add/nx;
+          long i = srch_add - j*nx;
 
-          if ( j < (ny-1) )
-            jp1 = j + 1;
-          else
-	    {
-	      /* 2008-12-17 Uwe Schulzweida: latitute cyclic ??? (bug fix) */
-	      jp1 = j;
-	    }
+          long ip1 = (i < (nx-1)) ? i + 1 : (src_grid->is_cyclic) ? 0 : i;
+          long jp1 = (j < (ny-1)) ? j + 1 : j;
 
-          n_add  = jp1*nx + i;
-          e_add  = j  *nx + ip1;
-	  ne_add = jp1*nx + ip1;
+          long n_add  = jp1*nx + i;
+          long e_add  = j  *nx + ip1;
+	  long ne_add = jp1*nx + ip1;
 
           src_lons[0] = src_center_lon[srch_add];
           src_lons[1] = src_center_lon[e_add];
@@ -432,10 +413,9 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
 	      next_n = (n+1)%4;
 
 	      /*
-		Here we take the cross product of the vector making 
-		up each box side with the vector formed by the vertex
-		and search point.  If all the cross products are 
-		positive, the point is contained in the box.
+		Here we take the cross product of the vector making up each box side 
+                with the vector formed by the vertex and search point.
+                If all the cross products are positive, the point is contained in the box.
 	      */
 	      vec1_lat = src_lats[next_n] - src_lats[n];
 	      vec1_lon = src_lons[next_n] - src_lons[n];
@@ -450,11 +430,10 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
 	      if      ( vec2_lon >  THREE*PIH ) vec2_lon -= PI2;
 	      else if ( vec2_lon < -THREE*PIH ) vec2_lon += PI2;
 
-	      cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat;
+	      double cross_product = vec1_lon*vec2_lat - vec2_lon*vec1_lat;
 
 	      /* If cross product is less than ZERO, this cell doesn't work    */
 	      /* 2008-10-16 Uwe Schulzweida: bug fix for cross_product eq zero */
-
 	      scross[n] = cross_product < 0 ? -1 : cross_product > 0 ? 1 : 0;
 
 	      if ( n == 0 ) scross_last = scross[n];
@@ -481,7 +460,7 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
 
 	      search_result = 1;
 
-	      return (search_result);
+	      return search_result;
 	    }
 
 	  /* Otherwise move on to next cell */
@@ -495,7 +474,7 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
     Go ahead and compute weights here, but store in src_lats and return -add to prevent the 
     parent routine from computing bilinear weights.
   */
-  if ( !src_grid->lextrapolate ) return (search_result);
+  if ( !src_grid->lextrapolate ) return search_result;
 
   /*
     printf("Could not find location for %g %g\n", plat*RAD2DEG, plon*RAD2DEG);
@@ -503,5 +482,5 @@ int grid_search(remapgrid_t *src_grid, int *restrict src_add, double *restrict s
   */
   search_result = grid_search_nn(min_add, max_add, src_add, src_lats, plat, plon, src_center_lat, src_center_lon);
 
-  return (search_result);
+  return search_result;
 }  /* grid_search */
diff --git a/src/remaplib.c b/src/remaplib.c
index 084438f..c7bdc7f 100644
--- a/src/remaplib.c
+++ b/src/remaplib.c
@@ -206,12 +206,8 @@ void remapgrid_alloc(int map_type, remapgrid_t *grid)
 
   if ( grid->lneed_cell_corners )
     {
-      if ( grid->num_cell_corners == 0 )
-	{
-	  cdoAbort("Grid cell corner missing!");
-	}
-      else
-	{
+      if ( grid->num_cell_corners > 0 )
+        {
 	  long nalloc = grid->num_cell_corners*grid->size;
 
 	  grid->cell_corner_lon = (double*) Malloc(nalloc*sizeof(double));
@@ -228,25 +224,20 @@ static
 void boundbox_from_corners(long size, long nc, const double *restrict corner_lon,
 			   const double *restrict corner_lat, restr_t *restrict bound_box)
 {
-  long i4, inc, j;
-  restr_t clon, clat;
-
 #if defined(_OPENMP)
-#pragma omp parallel for default(none)        \
-  shared(bound_box, corner_lat, corner_lon, nc, size)	\
-  private(i4, inc, j, clon, clat)
+#pragma omp parallel for default(none)  shared(bound_box, corner_lat, corner_lon, nc, size)
 #endif
   for ( long i = 0; i < size; ++i )
     {
-      i4 = i<<2; // *4
-      inc = i*nc;
-      clat = RESTR_SCALE(corner_lat[inc]);
-      clon = RESTR_SCALE(corner_lon[inc]);
+      long i4 = i<<2; // *4
+      long inc = i*nc;
+      restr_t clat = RESTR_SCALE(corner_lat[inc]);
+      restr_t clon = RESTR_SCALE(corner_lon[inc]);
       bound_box[i4  ] = clat;
       bound_box[i4+1] = clat;
       bound_box[i4+2] = clon;
       bound_box[i4+3] = clon;
-      for ( j = 1; j < nc; ++j )
+      for ( long j = 1; j < nc; ++j )
 	{
 	  clat = RESTR_SCALE(corner_lat[inc+j]);
 	  clon = RESTR_SCALE(corner_lon[inc+j]);
@@ -521,17 +512,7 @@ int expand_curvilinear_grid(int gridID)
       yvals[(nyp4-2)*nxp4+i] = intlin(2.0, yvals[(nyp4-4)*nxp4+i], 0.0, yvals[(nyp4-3)*nxp4+i], 1.0);
       yvals[(nyp4-1)*nxp4+i] = intlin(3.0, yvals[(nyp4-4)*nxp4+i], 0.0, yvals[(nyp4-3)*nxp4+i], 1.0);
     }
-  /*
-    {
-    FILE *fp;
-    fp = fopen("xvals.asc", "w");
-    for ( i = 0; i < gridsize_new; i++ ) fprintf(fp, "%g\n", xvals[i]);
-    fclose(fp);
-    fp = fopen("yvals.asc", "w");
-    for ( i = 0; i < gridsize_new; i++ ) fprintf(fp, "%g\n", yvals[i]);
-    fclose(fp);
-    }
-  */
+
   gridDefXvals(gridIDnew, xvals);
   gridDefYvals(gridIDnew, yvals);
   
@@ -867,7 +848,7 @@ void remap_grids_init(int map_type, bool lextrapolate, int gridID1, remapgrid_t
 
   int sgridID = src_grid->gridID;
   if ( gridInqSize(sgridID) > 1 && 
-       (gridInqType(sgridID) == GRID_LCC || 
+       ((gridInqType(sgridID) == GRID_PROJECTION && gridInqProjType(sgridID) == CDI_PROJ_LCC) || 
 	(gridInqType(sgridID) == GRID_PROJECTION && gridInqProjType(sgridID) == CDI_PROJ_LAEA) || 
 	(gridInqType(sgridID) == GRID_PROJECTION && gridInqProjType(sgridID) == CDI_PROJ_SINU)) )
     {
@@ -1180,7 +1161,7 @@ long get_max_add(long num_links, long size, const int *restrict add)
   for ( long i = 0; i < size; ++i ) if ( isum[i] > max_add ) max_add = isum[i];
   Free(isum);
 
-  return (max_add);
+  return max_add;
 }
 
 static 
diff --git a/src/sellist.c b/src/sellist.c
index b582faa..aab80ae 100644
--- a/src/sellist.c
+++ b/src/sellist.c
@@ -333,6 +333,17 @@ void sellist_def_val(sellist_t *sellist, int idx, int vindex, void *val)
     }
 }
 
+static
+void sellist_print_val(int type, cvalues_t *cvalues, int i)
+{
+  switch (type)
+    {
+    case SELLIST_INT:  printf(" %d", ((int*)cvalues)[i]); break;
+    case SELLIST_FLT:  printf(" %g", ((double*)cvalues)[i]); break;
+    case SELLIST_WORD: printf(" %s", ((char**)cvalues)[i]); break;
+    }
+}
+
 
 void sellist_print(sellist_t *sellist)
 {
@@ -345,15 +356,10 @@ void sellist_print(sellist_t *sellist)
           selentry_t *e = &(sellist->entry[idx]);
           printf("%3d  %-16s %4d  %4d ", idx+1, e->key, e->type, e->nvalues);
           int nvalues = e->nvalues;
-          if ( nvalues > 12 ) nvalues = 12;
-          for ( int i = 0; i < nvalues; ++i )
-            switch (e->type)
-              {
-              case SELLIST_INT:  printf(" %d", ((int*)e->cvalues)[i]); break;
-              case SELLIST_FLT:  printf(" %g", ((double*)e->cvalues)[i]); break;
-              case SELLIST_WORD: printf(" %s", ((char**)e->cvalues)[i]); break;
-              }
+          if ( nvalues > 12 ) nvalues = 11;
+          for ( int i = 0; i < nvalues; ++i ) sellist_print_val(e->type, (cvalues_t *)e->cvalues, i);
           if ( nvalues < e->nvalues ) printf(" ...");
+          sellist_print_val(e->type, (cvalues_t *)e->cvalues, e->nvalues-1);
           printf("\n");
         }
     }
diff --git a/src/specspace.c b/src/specspace.c
index fa35b3c..8ae0ef1 100644
--- a/src/specspace.c
+++ b/src/specspace.c
@@ -1,12 +1,6 @@
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
 #include "specspace.h"
-#include "error.h"
 #include "grid.h"
 
 
@@ -223,10 +217,10 @@ void trans_uv2dv(SPTRANS *sptrans, int nlev,
 		 int gridID2, double *sd, double *svo)
 {
   if ( gridInqType(gridID1) != GRID_GAUSSIAN )
-    Error("unexpected grid1 type: %s instead of Gaussian", gridNamePtr(gridInqType(gridID1)));
+    cdoAbort("unexpected grid1 type: %s instead of Gaussian", gridNamePtr(gridInqType(gridID1)));
 
   if ( gridInqType(gridID2) != GRID_SPECTRAL )
-    Error("unexpected grid2 type: %s instead of spectral", gridNamePtr(gridInqType(gridID2)));
+    cdoAbort("unexpected grid2 type: %s instead of spectral", gridNamePtr(gridInqType(gridID2)));
     
   int ntr   = gridInqTrunc(gridID2);
   int nlon  = gridInqXsize(gridID1);
diff --git a/src/stdnametable.c b/src/stdnametable.c
index 489c776..84e89dc 100644
--- a/src/stdnametable.c
+++ b/src/stdnametable.c
@@ -87,6 +87,9 @@ void echam_gribcodes(gribcode_t *gribcodes)
   gribcodes->ps      =  134;
   gribcodes->lsp     =  152;
   gribcodes->gheight =  156;
+  gribcodes->wind    =    0;  
+  gribcodes->uwind   =  131;
+  gribcodes->vwind   =  132;
 }
 
 
@@ -98,4 +101,42 @@ void wmo_gribcodes(gribcode_t *gribcodes)
   gribcodes->ps      =   1;
   gribcodes->lsp     =   0;
   gribcodes->gheight =   7;
+  gribcodes->wind    =   10;  
+  gribcodes->uwind   =   131;
+  gribcodes->vwind   =   132;
+   /*  ECMWF (IFS) GLOBAL Model
+    * 
+    * http://old.ecmwf.int/publications/manuals/d/gribapi/param/filter=grib1/order=paramId/order_type=asc/p=1/search=wind/table=128/
+    Wind speed	ws	m s**-1	10	grib1	grib2	          
+    U component of wind	u	m s**-1	131	grib1	grib2	netcdf
+    V component of wind	v	m s**-1	132	grib1	grib2	netcdf
+    10 metre U wind component	10u	m s**-1	165	grib1	grib2	          
+    10 metre V wind component	10v	m s**-1	166	grib1	grib2	          
+    10 metre wind speed	10si	m s**-1	207	grib1	grib2	          
+   */
+}
+
+
+void hirlam_harmonie_gribcodes(gribcode_t *gribcodes)
+{
+  gribcodes->geopot  =   6; // Geopotential [m2/s2]
+  gribcodes->temp    =  11; // Temperature [K]
+  gribcodes->hum     =  51; // Specific humidity [kg/kg]
+  gribcodes->ps      =   1; // Pressure [Pa]
+  gribcodes->lsp     =   0; // - not available -
+  gribcodes->gheight =   7; // 	007 Geopotential height [Gpm]; 008 Geometric height [m]
+  gribcodes->wind    =   32;  
+  gribcodes->uwind   =   33;
+  gribcodes->vwind   =   34;  
+  /*
+   1/103/0 	"mean sea level pressure" pressure_msl   [Pa]
+   1/105/0 	"surface pressure"  pressure_surf  [Pa]
+   032	Wind speed          	m/s 	WIND
+   033	u-component of wind 	m/s 	UGRD
+   034	v-component of wind 	m/s 	VGRD
+   051	Specific humidity
+   052	Relative humidity
+   NOT AVAILABLE:
+      - Natural log of surface pressure 	ln(kPa) 	NLGSP 
+   */
 }
diff --git a/src/stdnametable.h b/src/stdnametable.h
index 831c1e4..8501b03 100644
--- a/src/stdnametable.h
+++ b/src/stdnametable.h
@@ -26,9 +26,15 @@ typedef struct
   int ps;
   int lsp;
   int gheight;
+  int wind;
+  int uwind;
+  int vwind;
 } gribcode_t;
 
+enum {ECHAM_MODE, WMO_MODE, HIRLAM_MODE};
+
 void echam_gribcodes(gribcode_t *gribcodes);
 void wmo_gribcodes(gribcode_t *gribcodes);
+void hirlam_harmonie_gribcodes(gribcode_t *gribcodes);
 
 #endif
diff --git a/src/table.c b/src/table.c
index d1fcf7d..b79376b 100644
--- a/src/table.c
+++ b/src/table.c
@@ -18,12 +18,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 #include <cdi.h>
-#include "cdo.h"
 #include "util.h"
-#include "error.h"
 
 
 int defineTable(const char *tablearg)
@@ -48,7 +45,7 @@ int defineTable(const char *tablearg)
 
   if ( tableID == CDI_UNDEFID ) tableID = tableInq(-1, 0, tablename);
 
-  if ( tableID == CDI_UNDEFID ) Error("table <%s> not found", tablename);
+  if ( tableID == CDI_UNDEFID ) cdoAbort("table <%s> not found", tablename);
 
   return tableID;
 }
diff --git a/src/util.c b/src/util.c
index ad3c1eb..9ff9721 100644
--- a/src/util.c
+++ b/src/util.c
@@ -109,7 +109,7 @@ int cdoCompress          = FALSE;
 int cdoInteractive       = FALSE;
 int cdoParIO             = FALSE;
 int cdoRegulargrid       = FALSE;
-
+int cdoDebugExt          = 0;     //  Debug level for the KNMI extensions
 int cdoNumVarnames       = 0;
 char **cdoVarnames       = NULL;
 
@@ -390,6 +390,13 @@ void strtolower(char *str)
       str[i] = (char)tolower((int)str[i]);
 }
 
+void strtoupper(char *str)
+{
+  if ( str )
+    for ( size_t i = 0; str[i]; ++i )
+      str[i] = (char)toupper((int)str[i]);
+}
+
 
 const char *parameter2word(const char *string)
 {
@@ -879,3 +886,23 @@ void minmaxval(long nvals, double *array, int *imiss, double *minval, double *ma
   *minval = xmin;
   *maxval = xmax;
 }
+
+
+void cdo_check_round(void)
+{
+  static bool checked = false;
+  if ( !checked )
+    {
+      checked = true;
+#define NMAX 3
+      double vals2[NMAX];
+      double vals[NMAX] = {2783.333, 1.45678921, 1.54678921};
+      double rvals[NMAX] = {2783, 1, 2};
+      for ( int i = 0; i < NMAX; ++i )
+        {
+          vals2[i] = round(vals[i]);
+          if ( IS_NOT_EQUAL(vals2[i], rvals[i]) )
+            cdoAbort("Function round() produces wrong results!");
+        }
+    }
+}
diff --git a/src/util.h b/src/util.h
index ed0364d..d8956c6 100644
--- a/src/util.h
+++ b/src/util.h
@@ -89,6 +89,7 @@ extern int cdoDebug;
 extern int cdoCompress;
 extern int cdoInteractive;
 extern int cdoParIO;
+extern int cdoDebugExt;
 
 extern int cdoCompType;
 extern int cdoCompLevel;
@@ -220,6 +221,7 @@ int zaxisFromName(const char *zaxisname);
 /* refactor: moved here from cdo.h */
 int cdo_omp_get_thread_num(void);
 void strtolower(char *str);
+void strtoupper(char *str);
 
 /* refactor: moved here from cdo.c */
 void exp_run(int argc, char *argv[], const char *cdoExpName); // job.c
@@ -228,4 +230,6 @@ void printLibraries(void);  // features.c
 
 int wildcardmatch(const char *w, const char *s);
 
+void cdo_check_round(void);
+
 #endif  /* _UTIL_H */
diff --git a/src/zaxis.c b/src/zaxis.c
index 6674e13..881553b 100644
--- a/src/zaxis.c
+++ b/src/zaxis.c
@@ -15,15 +15,8 @@
   GNU General Public License for more details.
 */
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
 #include <cdi.h>
-#include "cdo.h"
 #include "cdo_int.h"
-#include "error.h"
 
 #define UNDEFID -1
 
@@ -92,8 +85,8 @@ int getoptname(char *optname, const char *optstring, int nopt)
 
 int zaxisDefine(zaxis_t zaxis)
 {
-  if ( zaxis.type == -1 ) Error("zaxistype undefined!");
-  if ( zaxis.size ==  0 ) Error("zaxis size undefined!");
+  if ( zaxis.type == -1 ) cdoAbort("zaxistype undefined!");
+  if ( zaxis.size ==  0 ) cdoAbort("zaxis size undefined!");
 
   int zaxisID = zaxisCreate(zaxis.type, zaxis.size);
 
@@ -124,7 +117,7 @@ int zaxisDefine(zaxis_t zaxis)
       if ( zaxis.vctsize && zaxis.vct )
 	zaxisDefVct(zaxisID, zaxis.vctsize, zaxis.vct);
       else
-	Warning("vct undefined!");	    
+	cdoWarning("vct undefined!");	    
     }
 
   return zaxisID;
diff --git a/test/Afterburner.test.in b/test/Afterburner.test.in
index 250a9a7..a03b74d 100644
--- a/test/Afterburner.test.in
+++ b/test/Afterburner.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 #
 AFTERTESTFILE=ECHAM5_T42L19.grb
 if [ -f "$CDOTESTDATA/$AFTERTESTFILE" -a "@ENABLE_CGRIBEX@" = yes ]; then
diff --git a/test/Arith.test.in b/test/Arith.test.in
index 67c4598..93514db 100644
--- a/test/Arith.test.in
+++ b/test/Arith.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..4 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Arithc.test.in b/test/Arithc.test.in
index 04f5f54..f036885 100644
--- a/test/Arithc.test.in
+++ b/test/Arithc.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..4 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Cat.test.in b/test/Cat.test.in
index a931582..2a4295f 100644
--- a/test/Cat.test.in
+++ b/test/Cat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Collgrid.test.in b/test/Collgrid.test.in
index 42f9797..4906176 100644
--- a/test/Collgrid.test.in
+++ b/test/Collgrid.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Comp.test.in b/test/Comp.test.in
index df3acce..65858f8 100644
--- a/test/Comp.test.in
+++ b/test/Comp.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..6 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Compc.test.in b/test/Compc.test.in
index 5abae87..05619f0 100644
--- a/test/Compc.test.in
+++ b/test/Compc.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..6 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Copy_netcdf.test.in b/test/Copy_netcdf.test.in
index cc4efd5..af0953f 100644
--- a/test/Copy_netcdf.test.in
+++ b/test/Copy_netcdf.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..5 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Detrend.test.in b/test/Detrend.test.in
index 1bf8c03..e129348 100644
--- a/test/Detrend.test.in
+++ b/test/Detrend.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..2 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/EOF.test.in b/test/EOF.test.in
index 4e2a6e6..7077f8b 100644
--- a/test/EOF.test.in
+++ b/test/EOF.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 #
 echo 1..2 # Number of tests to be executed.
 #
diff --git a/test/Enspctl.test.in b/test/Enspctl.test.in
index 62e8abe..e517104 100644
--- a/test/Enspctl.test.in
+++ b/test/Enspctl.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Ensstat.test.in b/test/Ensstat.test.in
index 1aadb19..6c1e0ad 100644
--- a/test/Ensstat.test.in
+++ b/test/Ensstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Expr.test.in b/test/Expr.test.in
index ee2c883..c806fb7 100644
--- a/test/Expr.test.in
+++ b/test/Expr.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..2 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/File.test.in b/test/File.test.in
index 8d0d00d..eefdb28 100644
--- a/test/File.test.in
+++ b/test/File.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..16 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Fldpctl.test.in b/test/Fldpctl.test.in
index 8344c6f..2829861 100644
--- a/test/Fldpctl.test.in
+++ b/test/Fldpctl.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Fldstat.test.in b/test/Fldstat.test.in
index 69a3665..92c45c4 100644
--- a/test/Fldstat.test.in
+++ b/test/Fldstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Genweights.test.in b/test/Genweights.test.in
index bf88738..44c985e 100644
--- a/test/Genweights.test.in
+++ b/test/Genweights.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 if [ "$USER" = "m214003" ]; then
 echo 1..32 # Number of tests to be executed.
 else
diff --git a/test/Gradsdes.test.in b/test/Gradsdes.test.in
index 225c466..e2299dd 100644
--- a/test/Gradsdes.test.in
+++ b/test/Gradsdes.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Gridarea.test.in b/test/Gridarea.test.in
index 45f2e00..442faba 100644
--- a/test/Gridarea.test.in
+++ b/test/Gridarea.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..7 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Gridboxstat.test.in b/test/Gridboxstat.test.in
index 7038ae7..2a624a6 100644
--- a/test/Gridboxstat.test.in
+++ b/test/Gridboxstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Makefile.am b/test/Makefile.am
index 8297062..60fbb59 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -13,7 +13,7 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
 # tests which should pass
 TESTS = threads.test tsformat.test wildcard.test File.test Comp.test Compc.test \
         Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test  \
-        Detrend.test Genweights.test Remap.test Select.test Spectral.test \
+        Detrend.test Genweights.test Remap.test Remap2.test Select.test Spectral.test \
         Ensstat.test Enspctl.test Gridboxstat.test \
         Vertstat.test Fldstat.test Fldpctl.test Merstat.test Zonstat.test \
         Timstat.test Timselstat.test Seasstat.test \
diff --git a/test/Makefile.in b/test/Makefile.in
index 4444989..77add64 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -85,21 +85,22 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(srcdir)/Copy_netcdf.test.in $(srcdir)/Comp.test.in \
 	$(srcdir)/Compc.test.in $(srcdir)/Cat.test.in \
 	$(srcdir)/Gridarea.test.in $(srcdir)/Genweights.test.in \
-	$(srcdir)/Remap.test.in $(srcdir)/EOF.test.in \
-	$(srcdir)/Select.test.in $(srcdir)/Spectral.test.in \
-	$(srcdir)/Vertint.test.in $(srcdir)/Timstat.test.in \
-	$(srcdir)/Timselstat.test.in $(srcdir)/Seasstat.test.in \
-	$(srcdir)/Runstat.test.in $(srcdir)/Multiyearstat.test.in \
-	$(srcdir)/Gridboxstat.test.in $(srcdir)/Vertstat.test.in \
-	$(srcdir)/Fldstat.test.in $(srcdir)/Fldpctl.test.in \
-	$(srcdir)/Ensstat.test.in $(srcdir)/Enspctl.test.in \
-	$(srcdir)/Merstat.test.in $(srcdir)/Zonstat.test.in \
-	$(srcdir)/Afterburner.test.in $(srcdir)/Detrend.test.in \
-	$(srcdir)/Arithc.test.in $(srcdir)/Arith.test.in \
-	$(srcdir)/Expr.test.in $(srcdir)/Gradsdes.test.in \
-	$(srcdir)/Collgrid.test.in $(srcdir)/threads.test.in \
-	$(srcdir)/tsformat.test.in $(srcdir)/wildcard.test.in \
-	$(srcdir)/MapReduce.test.in $(srcdir)/Ninfo.test.in README
+	$(srcdir)/Remap.test.in $(srcdir)/Remap2.test.in \
+	$(srcdir)/EOF.test.in $(srcdir)/Select.test.in \
+	$(srcdir)/Spectral.test.in $(srcdir)/Vertint.test.in \
+	$(srcdir)/Timstat.test.in $(srcdir)/Timselstat.test.in \
+	$(srcdir)/Seasstat.test.in $(srcdir)/Runstat.test.in \
+	$(srcdir)/Multiyearstat.test.in $(srcdir)/Gridboxstat.test.in \
+	$(srcdir)/Vertstat.test.in $(srcdir)/Fldstat.test.in \
+	$(srcdir)/Fldpctl.test.in $(srcdir)/Ensstat.test.in \
+	$(srcdir)/Enspctl.test.in $(srcdir)/Merstat.test.in \
+	$(srcdir)/Zonstat.test.in $(srcdir)/Afterburner.test.in \
+	$(srcdir)/Detrend.test.in $(srcdir)/Arithc.test.in \
+	$(srcdir)/Arith.test.in $(srcdir)/Expr.test.in \
+	$(srcdir)/Gradsdes.test.in $(srcdir)/Collgrid.test.in \
+	$(srcdir)/threads.test.in $(srcdir)/tsformat.test.in \
+	$(srcdir)/wildcard.test.in $(srcdir)/MapReduce.test.in \
+	$(srcdir)/Ninfo.test.in README
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/m4/acx_options.m4 \
 	$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \
@@ -112,14 +113,14 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/src/config.h
 CONFIG_CLEAN_FILES = File.test Read_grib.test Read_netcdf.test \
 	Copy_netcdf.test Comp.test Compc.test Cat.test Gridarea.test \
-	Genweights.test Remap.test EOF.test Select.test Spectral.test \
-	Vertint.test Timstat.test Timselstat.test Seasstat.test \
-	Runstat.test Multiyearstat.test Gridboxstat.test Vertstat.test \
-	Fldstat.test Fldpctl.test Ensstat.test Enspctl.test \
-	Merstat.test Zonstat.test Afterburner.test Detrend.test \
-	Arithc.test Arith.test Expr.test Gradsdes.test Collgrid.test \
-	threads.test tsformat.test wildcard.test MapReduce.test \
-	Ninfo.test
+	Genweights.test Remap.test Remap2.test EOF.test Select.test \
+	Spectral.test Vertint.test Timstat.test Timselstat.test \
+	Seasstat.test Runstat.test Multiyearstat.test Gridboxstat.test \
+	Vertstat.test Fldstat.test Fldpctl.test Ensstat.test \
+	Enspctl.test Merstat.test Zonstat.test Afterburner.test \
+	Detrend.test Arithc.test Arith.test Expr.test Gradsdes.test \
+	Collgrid.test threads.test tsformat.test wildcard.test \
+	MapReduce.test Ninfo.test
 CONFIG_CLEAN_VPATH_FILES =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
@@ -353,6 +354,7 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BASH = @BASH@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -530,7 +532,7 @@ TEST_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
 # tests which should pass
 TESTS = threads.test tsformat.test wildcard.test File.test Comp.test Compc.test \
         Read_grib.test Read_netcdf.test Copy_netcdf.test Cat.test Gridarea.test  \
-        Detrend.test Genweights.test Remap.test Select.test Spectral.test \
+        Detrend.test Genweights.test Remap.test Remap2.test Select.test Spectral.test \
         Ensstat.test Enspctl.test Gridboxstat.test \
         Vertstat.test Fldstat.test Fldpctl.test Merstat.test Zonstat.test \
         Timstat.test Timselstat.test Seasstat.test \
@@ -606,6 +608,8 @@ Genweights.test: $(top_builddir)/config.status $(srcdir)/Genweights.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Remap.test: $(top_builddir)/config.status $(srcdir)/Remap.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+Remap2.test: $(top_builddir)/config.status $(srcdir)/Remap2.test.in
+	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 EOF.test: $(top_builddir)/config.status $(srcdir)/EOF.test.in
 	cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
 Select.test: $(top_builddir)/config.status $(srcdir)/Select.test.in
diff --git a/test/MapReduce.test.in b/test/MapReduce.test.in
index 3d75b3f..b5288d7 100644
--- a/test/MapReduce.test.in
+++ b/test/MapReduce.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..2 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
@@ -28,7 +28,7 @@ for OPERATOR in reducegrid; do
       test $? -eq 0 || let RSTAT+=1
 
 #      $CDO griddes reduced_${grid}.nc > griddes.${grid}
-      $CDO griddes reduced_${grid}.nc | sed -e s-\"--g > griddes.${grid}
+      $CDO griddes reduced_${grid}.nc | sed -e s-\"--g | grep -v scanningMode > griddes.${grid}
       diff griddes.${grid} $REF
       test $? -eq 0 || let RSTAT+=1
 
diff --git a/test/Merstat.test.in b/test/Merstat.test.in
index 7ae2556..bb4d23a 100644
--- a/test/Merstat.test.in
+++ b/test/Merstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Multiyearstat.test.in b/test/Multiyearstat.test.in
index 110df7b..fc559ac 100644
--- a/test/Multiyearstat.test.in
+++ b/test/Multiyearstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..36 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Ninfo.test.in b/test/Ninfo.test.in
index 5d6a046..940e5dd 100644
--- a/test/Ninfo.test.in
+++ b/test/Ninfo.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
@@ -37,6 +37,7 @@ for grid  in r18x9 ni4 ni96 global_10 t63grid; do
   let NTEST+=1
 done
 # some addional test for operator: ngrids
+CDOTEST="ngrids"
 CDOCOMMAND="$CDO -O -s -ngrids"
 $CDOCOMMAND -topo,global_10
 test $? -eq 0 || let RSTAT+=1
diff --git a/test/Read_grib.test.in b/test/Read_grib.test.in
index 5499387..0a06478 100644
--- a/test/Read_grib.test.in
+++ b/test/Read_grib.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..6 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Read_netcdf.test.in b/test/Read_netcdf.test.in
index 958344b..ffac567 100644
--- a/test/Read_netcdf.test.in
+++ b/test/Read_netcdf.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..4 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Remap.test.in b/test/Remap.test.in
index 0b5e43a..0c76c9e 100644
--- a/test/Remap.test.in
+++ b/test/Remap.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 if [ "$USER" = "m214003" ]; then
 echo 1..32 # Number of tests to be executed.
 else
diff --git a/test/Remap2.test.in b/test/Remap2.test.in
new file mode 100644
index 0000000..60bdfde
--- /dev/null
+++ b/test/Remap2.test.in
@@ -0,0 +1,59 @@
+#! @BASH@
+echo 1..7 # Number of tests to be executed.
+#
+test -n "$CDO"      || CDO=cdo
+test -n "$DATAPATH" || DATAPATH=./data
+#
+ABSLIMMAX=0.0001
+ABSLIMDIS=0.001
+CDOOUT=cout$$
+CDOERR=cerr$$
+FORMAT="-f srv -b 32"
+GRID=$DATAPATH/spain.grid
+#
+IFILE=$DATAPATH/tsurf_spain.grb
+NTEST=1
+#
+RMODS="dis nn bil bic con ycon laf"
+for RMOD in $RMODS; do
+  ABSLIM=$ABSLIMMAX
+  if [ $RMOD = dis ];  then ABSLIM=$ABSLIMDIS; fi
+  CDOTEST="remap${RMOD} regional"
+  RSTAT=0
+  for extra in def off on; do
+    EXTRA="$extra"
+    if [ "$EXTRA" = "def" ]; then EXTRA=""; fi
+
+    OFILE=tsurf_spain_${RMOD}_${extra}$$
+    RFILE=$DATAPATH/tsurf_spain_${RMOD}_${extra}_ref
+
+    CDOCOMMAND="$CDO $FORMAT remap${RMOD},$GRID  $IFILE ${OFILE}"
+
+    echo "Running test: $NTEST"
+    echo "$CDOCOMMAND"
+
+    REMAP_EXTRAPOLATE=$EXTRA $CDOCOMMAND
+    test $? -eq 0 || let RSTAT+=1
+
+    $CDO diff,$ABSLIM $OFILE $RFILE > $CDOOUT 2> $CDOERR
+    test $? -eq 0 || let RSTAT+=1
+    test -s $CDOOUT && let RSTAT+=1
+    cat $CDOOUT $CDOERR
+
+    rm -f $OFILE
+  done
+
+  test $RSTAT -eq 0 && echo "ok $NTEST - $CDOTEST"
+  if [ $RMOD = dis ]; then
+    test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST # TODO check depends on optimization"
+  else
+    test $RSTAT -eq 0 || echo "not ok $NTEST - $CDOTEST"
+  fi
+
+  let NTEST+=1
+  rm -f $OFILE
+done
+#
+rm -f $CDOOUT $CDOERR
+#
+exit 0
diff --git a/test/Runstat.test.in b/test/Runstat.test.in
index 0d8cba3..3df185e 100644
--- a/test/Runstat.test.in
+++ b/test/Runstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Seasstat.test.in b/test/Seasstat.test.in
index 8a6f9d3..81ab0db 100644
--- a/test/Seasstat.test.in
+++ b/test/Seasstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Select.test.in b/test/Select.test.in
index 77a73c3..458f9d7 100644
--- a/test/Select.test.in
+++ b/test/Select.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..8 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Spectral.test.in b/test/Spectral.test.in
index 90a4352..797859a 100644
--- a/test/Spectral.test.in
+++ b/test/Spectral.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..4 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Timselstat.test.in b/test/Timselstat.test.in
index 5f840db..6967bcf 100644
--- a/test/Timselstat.test.in
+++ b/test/Timselstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Timstat.test.in b/test/Timstat.test.in
index 3b5c61a..62bac46 100644
--- a/test/Timstat.test.in
+++ b/test/Timstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..36 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Vertint.test.in b/test/Vertint.test.in
index 8e031b3..7a07df9 100644
--- a/test/Vertint.test.in
+++ b/test/Vertint.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Vertstat.test.in b/test/Vertstat.test.in
index 0cb8826..4358915 100644
--- a/test/Vertstat.test.in
+++ b/test/Vertstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..10 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/Zonstat.test.in b/test/Zonstat.test.in
index 8cc50b9..ac4c754 100644
--- a/test/Zonstat.test.in
+++ b/test/Zonstat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..9 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/data/Makefile.am b/test/data/Makefile.am
index 0cfacfa..c1f817e 100644
--- a/test/data/Makefile.am
+++ b/test/data/Makefile.am
@@ -1,6 +1,6 @@
 INPUTDATA = ts_mm_5years ts_6h_1mon ts_1d_1year hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data pl_data.grb detrend_data \
             grib_testfile01.grb grib_testfile02.grb grib_testfile03.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
-            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv psl_DJF_anom.grb
+            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv psl_DJF_anom.grb tsurf_spain.grb spain.grid
 
 FILE_REF     = file_F32_srv_ref
 GRIB_REF     = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref grib_testfile03_sinfo_ref grib_testfile03_info_ref
@@ -25,6 +25,11 @@ SPECTRAL_REF = sp2gp_ref sp2gpl_ref gp2sp_ref gp2spl_ref
 VERTINT_REF  = ml2pl_ref
 REMAP_REF    = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_nn_ref n16_dis_ref \
                n32_bic_ref n32_bil_ref n32_con_ref n32_ycon_ref n32_laf_ref n32_nn_ref n32_dis_ref
+REMAP2_REF   = tsurf_spain_bic_def_ref  tsurf_spain_bil_on_ref   tsurf_spain_dis_off_ref  tsurf_spain_nn_def_ref  tsurf_spain_ycon_on_ref \
+               tsurf_spain_bic_off_ref  tsurf_spain_con_def_ref  tsurf_spain_dis_on_ref   tsurf_spain_nn_off_ref \
+               tsurf_spain_bic_on_ref   tsurf_spain_con_off_ref  tsurf_spain_laf_def_ref  tsurf_spain_nn_on_ref \
+               tsurf_spain_bil_def_ref  tsurf_spain_con_on_ref   tsurf_spain_laf_off_ref  tsurf_spain_ycon_def_ref \
+               tsurf_spain_bil_off_ref  tsurf_spain_dis_def_ref  tsurf_spain_laf_on_ref   tsurf_spain_ycon_off_ref
 SELECT_REF   = select1_ref select2_ref select3_ref select4_ref select5_ref
 DETREND_REF  = detrend_ref
 EXPR_REF     = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
@@ -33,4 +38,7 @@ GRADSDES_REF = pl_data.ctl pl_data.gmp
 ARITH_REF    = arithadd_ref arithsub_ref arithmul_ref arithdiv_ref
 MAPREDUCE    = r18x9_grid icon_cell_grid griddes.r18x9 griddes.icon_cell
 
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(EOF_REF) $(COMP_REF) $(YMONSTAT_REF) $(YSEASSTAT_REF) $(SEASSTAT_REF) $(RUNSTAT_REF) $(TIMSTAT_REF) $(YEARSTAT_REF) $(MONSTAT_REF) $(DAYSTAT_REF) $(VERTSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(MERSTAT_REF) $(ZONSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(EOF_REF) $(COMP_REF) $(YMONSTAT_REF) $(YSEASSTAT_REF) $(SEASSTAT_REF) \
+             $(RUNSTAT_REF) $(TIMSTAT_REF) $(YEARSTAT_REF) $(MONSTAT_REF) $(DAYSTAT_REF) $(VERTSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) \
+             $(MERSTAT_REF) $(ZONSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(REMAP2_REF) $(SELECT_REF) $(DETREND_REF) \
+             $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
diff --git a/test/data/Makefile.in b/test/data/Makefile.in
index 7d57124..fb5de17 100644
--- a/test/data/Makefile.in
+++ b/test/data/Makefile.in
@@ -123,6 +123,7 @@ AUTOCONF = @AUTOCONF@
 AUTOHEADER = @AUTOHEADER@
 AUTOMAKE = @AUTOMAKE@
 AWK = @AWK@
+BASH = @BASH@
 CC = @CC@
 CCDEPMODE = @CCDEPMODE@
 CFLAGS = @CFLAGS@
@@ -287,7 +288,7 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 INPUTDATA = ts_mm_5years ts_6h_1mon ts_1d_1year hl_l19.grb t21_geosp_tsurf.grb bathy4.grb pl_data pl_data.grb detrend_data \
             grib_testfile01.grb grib_testfile02.grb grib_testfile03.grb netcdf_testfile01.nc netcdf_testfile02.nc testfile01c.nc \
-            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv psl_DJF_anom.grb
+            datar.nc datac.nc datau.nc datag.nc arith1.srv expr1.srv arithmask.srv psl_DJF_anom.grb tsurf_spain.grb spain.grid
 
 FILE_REF = file_F32_srv_ref
 GRIB_REF = grib_testfile01_sinfo_ref grib_testfile01_info_ref grib_testfile02_sinfo_ref grib_testfile02_info_ref grib_testfile03_sinfo_ref grib_testfile03_info_ref
@@ -313,6 +314,12 @@ VERTINT_REF = ml2pl_ref
 REMAP_REF = n16_bic_ref n16_bil_ref n16_con_ref n16_ycon_ref n16_laf_ref n16_nn_ref n16_dis_ref \
                n32_bic_ref n32_bil_ref n32_con_ref n32_ycon_ref n32_laf_ref n32_nn_ref n32_dis_ref
 
+REMAP2_REF = tsurf_spain_bic_def_ref  tsurf_spain_bil_on_ref   tsurf_spain_dis_off_ref  tsurf_spain_nn_def_ref  tsurf_spain_ycon_on_ref \
+               tsurf_spain_bic_off_ref  tsurf_spain_con_def_ref  tsurf_spain_dis_on_ref   tsurf_spain_nn_off_ref \
+               tsurf_spain_bic_on_ref   tsurf_spain_con_off_ref  tsurf_spain_laf_def_ref  tsurf_spain_nn_on_ref \
+               tsurf_spain_bil_def_ref  tsurf_spain_con_on_ref   tsurf_spain_laf_off_ref  tsurf_spain_ycon_def_ref \
+               tsurf_spain_bil_off_ref  tsurf_spain_dis_def_ref  tsurf_spain_laf_on_ref   tsurf_spain_ycon_off_ref
+
 SELECT_REF = select1_ref select2_ref select3_ref select4_ref select5_ref
 DETREND_REF = detrend_ref
 EXPR_REF = expr1_ref aexpr1_ref expr2_ref aexpr2_ref
@@ -320,7 +327,11 @@ THREAD_REF = thread1_ref tsformat1_ref
 GRADSDES_REF = pl_data.ctl pl_data.gmp
 ARITH_REF = arithadd_ref arithsub_ref arithmul_ref arithdiv_ref
 MAPREDUCE = r18x9_grid icon_cell_grid griddes.r18x9 griddes.icon_cell
-EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(EOF_REF) $(COMP_REF) $(YMONSTAT_REF) $(YSEASSTAT_REF) $(SEASSTAT_REF) $(RUNSTAT_REF) $(TIMSTAT_REF) $(YEARSTAT_REF) $(MONSTAT_REF) $(DAYSTAT_REF) $(VERTSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) $(MERSTAT_REF) $(ZONSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(SELECT_REF) $(DETREND_REF) $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
+EXTRA_DIST = $(INPUTDATA) $(FILE_REF) $(GRIB_REF) $(NETCDF_REF) $(EOF_REF) $(COMP_REF) $(YMONSTAT_REF) $(YSEASSTAT_REF) $(SEASSTAT_REF) \
+             $(RUNSTAT_REF) $(TIMSTAT_REF) $(YEARSTAT_REF) $(MONSTAT_REF) $(DAYSTAT_REF) $(VERTSTAT_REF) $(FLDSTAT_REF) $(FLDPSTAT_REF) \
+             $(MERSTAT_REF) $(ZONSTAT_REF) $(ENSPSTAT_REF) $(SPECTRAL_REF) $(VERTINT_REF) $(REMAP_REF) $(REMAP2_REF) $(SELECT_REF) $(DETREND_REF) \
+             $(THREAD_REF) $(EXPR_REF) $(GRADSDES_REF) $(ARITH_REF) $(MAPREDUCE)
+
 all: all-am
 
 .SUFFIXES:
diff --git a/test/data/spain.grid b/test/data/spain.grid
new file mode 100644
index 0000000..fe93735
--- /dev/null
+++ b/test/data/spain.grid
@@ -0,0 +1,7 @@
+gridtype=lonlat
+xsize=20
+ysize=18
+xfirst=-13
+yfirst=33
+xinc=.8
+yinc=.8
diff --git a/test/data/tsurf_spain.grb b/test/data/tsurf_spain.grb
new file mode 100644
index 0000000..f4e3fd5
Binary files /dev/null and b/test/data/tsurf_spain.grb differ
diff --git a/test/data/tsurf_spain_bic_def_ref b/test/data/tsurf_spain_bic_def_ref
new file mode 100644
index 0000000..f66cfec
Binary files /dev/null and b/test/data/tsurf_spain_bic_def_ref differ
diff --git a/test/data/tsurf_spain_bic_off_ref b/test/data/tsurf_spain_bic_off_ref
new file mode 100644
index 0000000..f66cfec
Binary files /dev/null and b/test/data/tsurf_spain_bic_off_ref differ
diff --git a/test/data/tsurf_spain_bic_on_ref b/test/data/tsurf_spain_bic_on_ref
new file mode 100644
index 0000000..b5b2e8e
Binary files /dev/null and b/test/data/tsurf_spain_bic_on_ref differ
diff --git a/test/data/tsurf_spain_bil_def_ref b/test/data/tsurf_spain_bil_def_ref
new file mode 100644
index 0000000..65c34d8
Binary files /dev/null and b/test/data/tsurf_spain_bil_def_ref differ
diff --git a/test/data/tsurf_spain_bil_off_ref b/test/data/tsurf_spain_bil_off_ref
new file mode 100644
index 0000000..65c34d8
Binary files /dev/null and b/test/data/tsurf_spain_bil_off_ref differ
diff --git a/test/data/tsurf_spain_bil_on_ref b/test/data/tsurf_spain_bil_on_ref
new file mode 100644
index 0000000..0a94f45
Binary files /dev/null and b/test/data/tsurf_spain_bil_on_ref differ
diff --git a/test/data/tsurf_spain_con_def_ref b/test/data/tsurf_spain_con_def_ref
new file mode 100644
index 0000000..223be76
Binary files /dev/null and b/test/data/tsurf_spain_con_def_ref differ
diff --git a/test/data/tsurf_spain_con_off_ref b/test/data/tsurf_spain_con_off_ref
new file mode 100644
index 0000000..223be76
Binary files /dev/null and b/test/data/tsurf_spain_con_off_ref differ
diff --git a/test/data/tsurf_spain_con_on_ref b/test/data/tsurf_spain_con_on_ref
new file mode 100644
index 0000000..223be76
Binary files /dev/null and b/test/data/tsurf_spain_con_on_ref differ
diff --git a/test/data/tsurf_spain_dis_def_ref b/test/data/tsurf_spain_dis_def_ref
new file mode 100644
index 0000000..f58b77f
Binary files /dev/null and b/test/data/tsurf_spain_dis_def_ref differ
diff --git a/test/data/tsurf_spain_dis_off_ref b/test/data/tsurf_spain_dis_off_ref
new file mode 100644
index 0000000..b2f38b8
Binary files /dev/null and b/test/data/tsurf_spain_dis_off_ref differ
diff --git a/test/data/tsurf_spain_dis_on_ref b/test/data/tsurf_spain_dis_on_ref
new file mode 100644
index 0000000..f58b77f
Binary files /dev/null and b/test/data/tsurf_spain_dis_on_ref differ
diff --git a/test/data/tsurf_spain_laf_def_ref b/test/data/tsurf_spain_laf_def_ref
new file mode 100644
index 0000000..e11cfac
Binary files /dev/null and b/test/data/tsurf_spain_laf_def_ref differ
diff --git a/test/data/tsurf_spain_laf_off_ref b/test/data/tsurf_spain_laf_off_ref
new file mode 100644
index 0000000..e11cfac
Binary files /dev/null and b/test/data/tsurf_spain_laf_off_ref differ
diff --git a/test/data/tsurf_spain_laf_on_ref b/test/data/tsurf_spain_laf_on_ref
new file mode 100644
index 0000000..e11cfac
Binary files /dev/null and b/test/data/tsurf_spain_laf_on_ref differ
diff --git a/test/data/tsurf_spain_nn_def_ref b/test/data/tsurf_spain_nn_def_ref
new file mode 100644
index 0000000..b13d918
Binary files /dev/null and b/test/data/tsurf_spain_nn_def_ref differ
diff --git a/test/data/tsurf_spain_nn_off_ref b/test/data/tsurf_spain_nn_off_ref
new file mode 100644
index 0000000..45ddf1a
Binary files /dev/null and b/test/data/tsurf_spain_nn_off_ref differ
diff --git a/test/data/tsurf_spain_nn_on_ref b/test/data/tsurf_spain_nn_on_ref
new file mode 100644
index 0000000..b13d918
Binary files /dev/null and b/test/data/tsurf_spain_nn_on_ref differ
diff --git a/test/data/tsurf_spain_ycon_def_ref b/test/data/tsurf_spain_ycon_def_ref
new file mode 100644
index 0000000..c0e03de
Binary files /dev/null and b/test/data/tsurf_spain_ycon_def_ref differ
diff --git a/test/data/tsurf_spain_ycon_off_ref b/test/data/tsurf_spain_ycon_off_ref
new file mode 100644
index 0000000..c0e03de
Binary files /dev/null and b/test/data/tsurf_spain_ycon_off_ref differ
diff --git a/test/data/tsurf_spain_ycon_on_ref b/test/data/tsurf_spain_ycon_on_ref
new file mode 100644
index 0000000..c0e03de
Binary files /dev/null and b/test/data/tsurf_spain_ycon_on_ref differ
diff --git a/test/threads.test.in b/test/threads.test.in
index d2a1d46..e814768 100644
--- a/test/threads.test.in
+++ b/test/threads.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..1 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/tsformat.test.in b/test/tsformat.test.in
index bb66643..ad21bcf 100644
--- a/test/tsformat.test.in
+++ b/test/tsformat.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 echo 1..8 # Number of tests to be executed.
 #
 test -n "$CDO"      || CDO=cdo
diff --git a/test/wildcard.test.in b/test/wildcard.test.in
index 4387360..789baf4 100644
--- a/test/wildcard.test.in
+++ b/test/wildcard.test.in
@@ -1,4 +1,4 @@
-#! @SHELL@
+#! @BASH@
 
 # Checks whether cdo handles the inputargument right,
 # most of the operators accept only one input argument.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/cdo.git



More information about the debian-science-commits mailing list