Erroneous behaviour setting GRIB2 bitsPerValue
Hi,
Recently, I've encountered a problem regarding the creation of GRIB2 files and, in particular, the setting of the bitsPerValue
information. One might argue if the following problem is caused by an erroneous behaviour of the CDI or the underlying ECCodes library:
To reproduce the problem, I've created a branch ex_bitsPerValue
where I modified the example program examples/cdi_write.c
accordingly (commit 2f5f90b9). Here, the CDI library creates a multi-level variable "QC" and sets
vlistDefVarDatatype(vlistID, varID2, 16);
We can see that this information is forwarded to the ECCodes library:
CDI_DEBUG=1 CDI_GRIBAPI_DEBUG=1 ./cdi_write
cdiGetenvInt : set CDI_GRIBAPI_DEBUG to 1
vlistCreate : create vlistID = 26
vlistDefVarTiles : gridID = 24 zaxisID = 25 timetype = 1
taxisCreate : taxistype: 1
taxisCreate : taxisID: 27
streamOpenID : Open GRIB2 mode w file example.grb
vlistDuplicate : call to vlistDuplicate
vlistCreate : create vlistID = 29
vlistCopy : call to vlistCopy, vlistIDs 26 -> 29
stream_new_var : gridID = 24 zaxisID = 25
stream_new_var : varID 0: create 1 tiles with 5 level(s), zaxisID=25
stream_new_var : streamptr->vars[varID].recordTable[isub].recordID[0]=-1
grib_set_long( grib_handle* h, "grib2LocalSectionPresent", 0)
grib_set_long( grib_handle* h, "numberOfValues", 0)
cdiStreamDefTimestep_: streamID = 28 tsID = 0
cdiStreamWriteVar_: streamID = 28 varID = 0
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "typeOfGeneratingProcess", 0)
grib_set_long( grib_handle* h, "backgroundProcess", 0)
grib_set_long( grib_handle* h, "productDefinitionTemplateNumber", 0)
grib_set_string( grib_handle* h, "stepType", "instant")
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850101)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_string( grib_handle* h, "shortName", "QC")
grib_set_long( grib_handle* h, "shapeOfTheEarth", 0)
grib_set_long( grib_handle* h, "bitsPerValue", 16)
grib_set_string( grib_handle* h, "packingType", "grid_simple")
grib_set_long( grib_handle* h, "numberOfValues", 72)
grib_set_string( grib_handle* h, "gridType", "regular_ll")
grib_set_long( grib_handle* h, "Ni", 12)
grib_set_double( grib_handle* h, "longitudeOfFirstGridPointInDegrees", 0.000000)
grib_set_double( grib_handle* h, "longitudeOfLastGridPointInDegrees", 330.000000)
grib_set_double( grib_handle* h, "iDirectionIncrementInDegrees", 30.000000)
grib_set_long( grib_handle* h, "Nj", 6)
grib_set_double( grib_handle* h, "latitudeOfFirstGridPointInDegrees", -75.000000)
grib_set_double( grib_handle* h, "latitudeOfLastGridPointInDegrees", 75.000000)
grib_set_long( grib_handle* h, "iScansNegatively", 0)
grib_set_long( grib_handle* h, "jScansPositively", 1)
grib_set_double( grib_handle* h, "jDirectionIncrementInDegrees", 30.000000)
grib_set_long( grib_handle* h, "typeOfFirstFixedSurface", 100)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 101300)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850101)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 92500)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850101)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 85000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850101)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 50000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850101)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 20000)
cdiStreamDefTimestep_: streamID = 28 tsID = 1
cdiStreamWriteVar_: streamID = 28 varID = 0
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850102)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 101300)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850102)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 92500)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850102)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 85000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850102)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 50000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850102)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 20000)
cdiStreamDefTimestep_: streamID = 28 tsID = 2
cdiStreamWriteVar_: streamID = 28 varID = 0
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850103)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 101300)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850103)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 92500)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850103)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 85000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850103)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 50000)
grb_write_var_slice: gridID = 24 zaxisID = 25
grib_set_long( grib_handle* h, "significanceOfReferenceTime", 0)
grib_set_long( grib_handle* h, "stepRange", 0)
grib_set_long( grib_handle* h, "dataDate", 19850103)
grib_set_long( grib_handle* h, "hour", 12)
grib_set_long( grib_handle* h, "minute", 0)
grib_set_long( grib_handle* h, "second", 0)
grib_set_long( grib_handle* h, "scaleFactorOfFirstFixedSurface", 0)
grib_set_long( grib_handle* h, "scaledValueOfFirstFixedSurface", 20000)
streamClose : streamID = 28 filename = example.grb
vlist_delete : call to vlist_delete, vlistID = 29
stream_delete_entry: Removed idx 28 from stream list
vlist_delete : call to vlist_delete, vlistID = 26
However, what's special about my setup is the fact that the first levels of my example are constant.
Therefore we see in the example output bitsPerValue=0
- I interpret this as "all values are equal, therefore GRIB2 encodes this in a trivial way".
But when we write out a mixture of constant and non-constant records, we get a problem: ECCodes obviously recognizes the first levels as constant (bitsPerValue=0
) and does not apply the original CDI setting bitsPerValue=16
. But this information is not restored when the non-constant QC levels are written: We get bitsPerValue=24
for these levels instead of 24 bits.
More precisely: If we enable the code section
// Init var2
for ( size_t i = 0; i < nlon*nlat*2; i++ ) var2[i] = 0.;
for ( size_t i = nlon*nlat*2; i < nlon*nlat*nlev; i++ ) var2[i] = sin((double)i);
i.e. a mixture of constant and non-constant levels, we get
$ /sw/rhel6-x64/eccodes/eccodes-2.5.0-intel14/bin/grib_ls -P bitsPerValue example.grb
example.grb
bitsPerValue edition centre date dataType gridType stepRange typeOfLevel level shortName packingType
0 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
0 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 925 qc grid_simple
24 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 850 qc grid_simple
24 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 500 qc grid_simple
24 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 200 qc grid_simple
0 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
0 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 925 qc grid_simple
24 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 850 qc grid_simple
24 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 500 qc grid_simple
24 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 200 qc grid_simple
0 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
0 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 925 qc grid_simple
24 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 850 qc grid_simple
24 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 500 qc grid_simple
24 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 200 qc grid_simple
On the other hand, if we have all levels non-constant:
// Init var2
for ( size_t i = 0; i < nlon*nlat*nlev; i++ ) var2[i] = sin((double)i);
we get
$ /sw/rhel6-x64/eccodes/eccodes-2.5.0-intel14/bin/grib_ls -P bitsPerValue example.grb
example.grb
bitsPerValue edition centre date dataType gridType stepRange typeOfLevel level shortName packingType
16 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
16 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 925 qc grid_simple
16 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 850 qc grid_simple
16 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 500 qc grid_simple
16 2 ecmf 19850101 af regular_ll 0 isobaricInhPa 200 qc grid_simple
16 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
16 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 925 qc grid_simple
16 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 850 qc grid_simple
16 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 500 qc grid_simple
16 2 ecmf 19850102 af regular_ll 0 isobaricInhPa 200 qc grid_simple
16 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 1013 qc grid_simple
16 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 925 qc grid_simple
16 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 850 qc grid_simple
16 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 500 qc grid_simple
16 2 ecmf 19850103 af regular_ll 0 isobaricInhPa 200 qc grid_simple