Repository: Unidata/netcdf-c (c)

Issue:
Reading HDF5 - control creation of anonymous dimensions
I've read the [Interoperability with HDF5](https://www.unidata.ucar.edu/software/netcdf/docs/interoperability_hdf5.html) section in the docs. 

_Assuming a HDF5 file is written in accordance with the netCDF-4 rules (i.e. no strange types, no looping groups), and assuming that every dataset has a dimension scale attached to each dimension, the netCDF-4 API can be used to read and edit the file, quite easily.
[...]
**If dimension scales are not used, then netCDF-4 can still edit the file, and will invent anonymous dimensions for each variable shape.**_

This works quite well when reading hdf5 weather radar data, but has one quirk.

If the variable has different size for first and second dimension (eg. `(100,200)`) two anonymous dimensions are invented. If the 2D dataset has same size for first and second dimension (eg. `(100,100)`) then only one anonymous dimension is invented.

In my use case this contradicts the original meaning of the 2D dataset dimensions to be different. Maybe I do not see it immediately, but I also can't think of any use case where the dimensions of a 2D dataset would be the same dimension (sound pretty bad, but I do not know how to explain better).

On my way to find some working solution I've already asked on the [netCDF4-python github issue tracker](https://github.com/Unidata/netcdf4-python/issues/945)  and on the `h5py` [mailing-list](https://groups.google.com/forum/#!topic/h5py/-OhSm8weTXk) but it seems a solution is only possible by enhancing/changing behaviour of netcdf-c.

From my perspective netcdf-c would need to invent two anonymous dimensions from a 2D dataset, even if the dimensions are of the same size. Another option would be to define the wanted behaviour at reading time. Are there any other options?


**Software Version Information**

<br/>
output of `nc-config --all (nectCDF 4.6.2):
<details>
This netCDF 4.6.2 has been built with the following features: 

  --cc            -> x86_64-conda_cos6-linux-gnu-cc
  --cflags        -> -I/home/kai/miniconda/envs/wradlib_150/include
  --libs          -> -L/home/kai/miniconda/envs/wradlib_150/lib -lnetcdf -lmfhdf -ldf -lhdf5_hl -lhdf5 -lrt -lpthread -lz -ldl -lm -lcurl

  --has-c++       -> no
  --cxx           -> 

  --has-c++4      -> no
  --cxx4          -> 

  --has-fortran   -> no
  --has-dap       -> yes
  --has-dap2      -> yes
  --has-dap4      -> yes
  --has-nc2       -> yes
  --has-nc4       -> yes
  --has-hdf5      -> yes
  --has-hdf4      -> yes
  --has-logging   -> no
  --has-pnetcdf   -> no
  --has-szlib     -> no
  --has-cdf5      -> yes
  --has-parallel4 -> no
  --has-parallel  -> no

  --prefix        -> /home/kai/miniconda/envs/wradlib_150
  --includedir    -> /home/kai/miniconda/envs/wradlib_150/include
  --libdir        -> /home/kai/miniconda/envs/wradlib_150/lib
  --version       -> netCDF 4.6.2
</details>

output of `h5cc --showconfig (hdf 1.10.5):
<details>
            SUMMARY OF THE HDF5 CONFIGURATION                                                                                                                           
            =================================                                                                                                                           
                                                                                                                                                                        
General Information:                                                                                                                                                    
-------------------                                                                                                                                                     
                   HDF5 Version: 1.10.5                                                                                                                                 
                  Configured on: Wed Aug 21 19:09:16 UTC 2019                                                                                                           
                  Configured by: conda@752c21c7e9bc                                                                                                                     
                    Host system: x86_64-conda_cos6-linux-gnu                                                                                                            
              Uname information: Linux 752c21c7e9bc 4.15.0-1052-azure #57-Ubuntu SMP Tue Jul 23 19:07:16 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux                        
                       Byte sex: little-endian                                                                                                                          
             Installation point: /home/kai/miniconda/envs/wradlib_150                                                                                                   

Compiling Options:
------------------
                     Build Mode: production
              Debugging Symbols: no
                        Asserts: no
                      Profiling: no
             Optimization Level: high

Linking Options:
----------------
                      Libraries: static, shared
  Statically Linked Executables: 
                        LDFLAGS: -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-rpath,/home/kai/miniconda/envs/wradlib_150/lib -Wl,-rpath-link,/home/kai/miniconda/envs/wradlib_150/lib -L/home/kai/miniconda/envs/wradlib_150/lib
                     H5_LDFLAGS: 
                     AM_LDFLAGS:  -L/home/kai/miniconda/envs/wradlib_150/lib
                Extra libraries: -lrt -lpthread -lz -ldl -lm 
                       Archiver: /home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/_build_env/bin/x86_64-conda_cos6-linux-gnu-ar
                       AR_FLAGS: cr
                         Ranlib: /home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/_build_env/bin/x86_64-conda_cos6-linux-gnu-ranlib

Languages:
----------
                              C: yes
                     C Compiler: /home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/_build_env/bin/x86_64-conda_cos6-linux-gnu-cc
                       CPPFLAGS: -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -I/home/kai/miniconda/envs/wradlib_150/include
                    H5_CPPFLAGS: -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L   -DNDEBUG -UH5_DEBUG_API
                    AM_CPPFLAGS:  -I/home/kai/miniconda/envs/wradlib_150/include
                        C Flags: -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -I/home/kai/miniconda/envs/wradlib_150/include -fdebug-prefix-map=/home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/work=/usr/local/src/conda/hdf5_split-1.10.5 -fdebug-prefix-map=/home/kai/miniconda/envs/wradlib_150=/usr/local/src/conda-prefix
                     H5 C Flags:  -std=c99  -pedantic -Wall -Wextra -Wbad-function-cast -Wc++-compat -Wcast-align -Wcast-qual -Wconversion -Wdeclaration-after-statement -Wdisabled-optimization -Wfloat-equal -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-declarations -Wmissing-include-dirs -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wpacked -Wpointer-arith -Wredundant-decls -Wshadow -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wundef -Wunused-macros -Wunsafe-loop-optimizations -Wwrite-strings -finline-functions -s -Wno-inline -Wno-aggregate-return -Wno-missing-format-attribute -Wno-missing-noreturn -O
                     AM C Flags: 
               Shared C Library: yes
               Static C Library: yes


                        Fortran: yes
               Fortran Compiler: /home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/_build_env/bin/x86_64-conda_cos6-linux-gnu-gfortran
                  Fortran Flags: 
               H5 Fortran Flags:  -pedantic -Wall -Wextra -Wunderflow -Wimplicit-interface -Wsurprising -Wno-c-binding-type  -s -O2
               AM Fortran Flags: 
         Shared Fortran Library: yes
         Static Fortran Library: yes

                            C++: yes
                   C++ Compiler: /home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/_build_env/bin/x86_64-conda_cos6-linux-gnu-c++
                      C++ Flags: -fvisibility-inlines-hidden -std=c++17 -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -I/home/kai/miniconda/envs/wradlib_150/include -fdebug-prefix-map=/home/conda/feedstock_root/build_artifacts/hdf5_split_1566414109997/work=/usr/local/src/conda/hdf5_split-1.10.5 -fdebug-prefix-map=/home/kai/miniconda/envs/wradlib_150=/usr/local/src/conda-prefix
                   H5 C++ Flags:   -pedantic -Wall -W -Wundef -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wredundant-decls -Winline -Wsign-promo -Woverloaded-virtual -Wold-style-cast -Weffc++ -Wreorder -Wnon-virtual-dtor -Wctor-dtor-privacy -Wabi -finline-functions -s -O
                   AM C++ Flags: 
             Shared C++ Library: yes
             Static C++ Library: yes

                           Java: no


Features:
---------
                   Parallel HDF5: no
Parallel Filtered Dataset Writes: no
              Large Parallel I/O: no
              High-level library: yes
                    Threadsafety: yes
             Default API mapping: v110
  With deprecated public symbols: yes
          I/O filters (external): deflate(zlib)
                             MPE: no
                      Direct VFD: no
                         dmalloc: no
  Packages w/ extra debug output: none
                     API tracing: no
            Using memory checker: yes
 Memory allocation sanity checks: no
          Function stack tracing: no
       Strict file format checks: no
    Optimization instrumentation: no
</details>

Python Version
```
Python 3.7.3 | packaged by conda-forge | (default, Jul  1 2019, 21:52:21) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
```

netCDF4 version
```
'1.5.1.2'
```

h5py version
```
'2.9.0'
```


Pull request description:
If HDF5 dataset has multiple anonymous dimensions of the same size, assume they are different dimensions
Fixes #1484 

When reading a HDF5 file (i.e. not a netCDF-4/HDF5 file), the library has to make assumptions about dimensions.

Until now, each dataspace length got it's own phony dimension, unless it was the same length as a previously assigned anon dimension.

That meant a HDF5 file with a 2-D dataspace of 100x100 would look like this:

```
netcdf dset {
dimensions:
        phony_dim_0 = 100 ;
variables:
        int dset(phony_dim_0, phony_dim_0) ;
}

```

This is probably not what the data writer intended. The two dimensions of the dataset should be two different dimensions, even though they are (coincidentally) the same size.

Now, if an anon dimension of the same size is found, it is also checked to see if it was already used in this dataset. If so, we now assume that it is a new dimension.

So now a HDF5 file, with two datasets of size 100 x 100 will look like this to netCDF:

```
netcdf tst_interops_dims {
dimensions:
	phony_dim_0 = 100 ;
	phony_dim_1 = 100 ;
variables:
	int dset(phony_dim_0, phony_dim_1) ;
	int dset2(phony_dim_0, phony_dim_1) ;
```

Note: this PR also includes #1523 

Patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 74f3acf54..7bb56bcb1 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -7,6 +7,8 @@ This file contains a high-level description of this package's evolution. Release
 
 ## 4.7.3 - TBD
 
+* [Bug Fix][Enhancement] Corrected assignment of anonymous (a.k.a. phony) dimensions in an HDF5 file. Now when a dataset uses multiple dimensions of the same size, netcdf assumes they are different dimensions. See [GitHub #1484](https://github.com/Unidata/netcdf-c/issues/1484) for more information.
+
 ## 4.7.2 - October 22, 2019
 
 * [Bug Fix][Enhancement] Various bug fixes and enhancements.
diff --git a/docs/tutorial.dox b/docs/tutorial.dox
index bcd8c6a49..2d342765b 100644
--- a/docs/tutorial.dox
+++ b/docs/tutorial.dox
@@ -708,7 +708,9 @@ deserve what you get, which will be a mess.
 Additionally, netCDF stores some extra information for dimensions
 without dimension scale information. (That is, a dimension without an
 associated coordinate variable). So HDF5 users should not write data
-to a netCDF-4 file which extends any unlimited dimension.
+to a netCDF-4 file which extends any unlimited dimension, or change
+any of the extra attributes used by netCDF to track dimension
+information.
 
 Also there are some types allowed in HDF5, but not allowed in netCDF-4
 (for example the time type). Using any such type in a netCDF-4 file
@@ -736,7 +738,20 @@ example, a user might have 1D dimension scales for lat and lon, and a
 the second.
 
 If dimension scales are not used, then netCDF-4 can still edit the
-file, and will invent anonymous dimensions for each variable shape.
+file, and will invent anonymous dimensions for each variable
+shape. This is done by iterating through the space of each dataset. As
+each space size is encountered, a phony dimension of that size is
+checked for. It it does not exist, a new phony dimension is created
+for that size. In this way, a HDF5 file with datasets that are using
+shared dimensions can be seen properly in netCDF-4. (There is no
+shared dimension in HDF5, but data users will freqently write many
+datasets with the same shape, and intend these to be shared
+dimensions.)
+
+Starting with version 4.7.3, if a dataset is encountered with uses the
+same size for two or more of its dataspace lengths, then a new phony
+dimension will be created for each. That is, a dataset with size
+[100][100] will result in two phony dimensions, each of size 100.
 
 \page groups Groups
 
diff --git a/libdispatch/dinfermodel.c b/libdispatch/dinfermodel.c
index 5f8b430cc..b037c8be8 100644
--- a/libdispatch/dinfermodel.c
+++ b/libdispatch/dinfermodel.c
@@ -395,6 +395,16 @@ NC_omodeinfer(int useparallel, int cmode, NCmodel* model)
 
     /* Process the cmode; may override some already set flags */
 
+    if(fIsSet(cmode,(NC_UDF0|NC_UDF1))) {
+	model->format = NC_FORMAT_NETCDF4;
+        if(fIsSet(cmode,NC_UDF0)) {
+	    model->impl = NC_FORMATX_UDF0;
+	} else {
+	    model->impl = NC_FORMATX_UDF1;
+	}
+	goto done;
+    }
+
     if(fIsSet(cmode,NC_64BIT_OFFSET)) {
 	model->impl = NC_FORMATX_NC3;
 	model->format = NC_FORMAT_64BIT_OFFSET;
@@ -416,16 +426,6 @@ NC_omodeinfer(int useparallel, int cmode, NCmodel* model)
         goto done;
     }
 
-    if(fIsSet(cmode,(NC_UDF0|NC_UDF1))) {
-	model->format = NC_FORMAT_NETCDF4;
-        if(fIsSet(cmode,NC_UDF0)) {
-	    model->impl = NC_FORMATX_UDF0;
-	} else {
-	    model->impl = NC_FORMATX_UDF1;
-	}
-	goto done;
-    }
-
     /* Default to classic model */
     model->format = NC_FORMAT_CLASSIC;
     model->impl = NC_FORMATX_NC3;
diff --git a/libhdf5/hdf5open.c b/libhdf5/hdf5open.c
index 34ab86ecc..38362d0c7 100644
--- a/libhdf5/hdf5open.c
+++ b/libhdf5/hdf5open.c
@@ -357,8 +357,11 @@ dimscale_visitor(hid_t did, unsigned dim, hid_t dsid,
 }
 
 /**
- * @internal For files without any netCDF-4 dimensions defined, create phony
- * dimension to match the available datasets.
+ * @internal For files without any netCDF-4 dimensions defined, create
+ * phony dimension to match the available datasets. Each new dimension
+ * of a new size gets a phony dimension. However, if a var has more
+ * than one dimension defined, and they are the same size, they each
+ * get their own phony dimension (starting in netcdf-c-4.7.3).
  *
  * @param grp Pointer to the group info.
  * @param hdf_datasetid HDF5 datsetid for the var's dataset.
@@ -409,21 +412,35 @@ create_phony_dims(NC_GRP_INFO_T *grp, hid_t hdf_datasetid, NC_VAR_INFO_T *var)
     for (d = 0; d < var->ndims; d++)
     {
         int k;
-        int match;
+        int match = 0;
 
         /* Is there already a phony dimension of the correct size? */
-        for (match=-1, k = 0; k < ncindexsize(grp->dim); k++)
+        for (k = 0; k < ncindexsize(grp->dim); k++)
         {
             dim = (NC_DIM_INFO_T *)ncindexith(grp->dim, k);
             assert(dim);
             if ((dim->len == h5dimlen[d]) &&
                 ((h5dimlenmax[d] == H5S_UNLIMITED && dim->unlimited) ||
                  (h5dimlenmax[d] != H5S_UNLIMITED && !dim->unlimited)))
-            {match = k; break;}
+            {
+                int k1;
+
+                /* We found a match! */
+                match++;
+
+                /* If this phony dimension has already in use for this
+                 * var, we should not use it again. */
+                for (k1 = 0; k1 < d; k1++)
+                    if (var->dimids[k1] == dim->hdr.id)
+                        match = 0;
+
+                if (match)
+                    break;
+            }
         }
 
         /* Didn't find a phony dim? Then create one. */
-        if (match < 0)
+        if (!match)
         {
             char phony_dim_name[NC_MAX_NAME + 1];
             sprintf(phony_dim_name, "phony_dim_%d", grp->nc4_info->next_dimid);


Test patch:
diff --git a/nc_test4/CMakeLists.txt b/nc_test4/CMakeLists.txt
index 50eed3fe4..fd2a16339 100644
--- a/nc_test4/CMakeLists.txt
+++ b/nc_test4/CMakeLists.txt
@@ -13,7 +13,7 @@ SET(NC4_TESTS tst_dims tst_dims2 tst_dims3 tst_files tst_files4
   tst_vars tst_varms tst_unlim_vars tst_converts tst_converts2
   tst_grps tst_grps2 tst_compounds tst_compounds2 tst_compounds3
   tst_opaques tst_strings tst_strings2 tst_interops tst_interops4
-  tst_interops6 tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3
+  tst_interops6 tst_interops_dims tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3
   tst_vars4 tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2
   tst_fillbug tst_xplatform2 tst_endian_fill tst_atts t_type
   cdm_sea_soundings tst_vl tst_atts1 tst_atts2 tst_vars2 tst_files5
diff --git a/nc_test4/Makefile.am b/nc_test4/Makefile.am
index 422bad33d..455677880 100644
--- a/nc_test4/Makefile.am
+++ b/nc_test4/Makefile.am
@@ -27,15 +27,16 @@ NC4_TESTS = tst_dims tst_dims2 tst_dims3 tst_files tst_files4		\
 tst_vars tst_varms tst_unlim_vars tst_converts tst_converts2 tst_grps	\
 tst_grps2 tst_compounds tst_compounds2 tst_compounds3 tst_opaques	\
 tst_strings tst_strings2 tst_interops tst_interops4 tst_interops5	\
-tst_interops6 tst_enums tst_coords tst_coords2 tst_coords3 tst_vars3	\
-tst_vars4 tst_chunks tst_chunks2 tst_utf8 tst_fills tst_fills2		\
-tst_fillbug tst_xplatform tst_xplatform2 tst_endian_fill tst_atts	\
-t_type cdm_sea_soundings tst_camrun tst_vl tst_atts1 tst_atts2		\
-tst_vars2 tst_files5 tst_files6 tst_sync tst_h_scalar tst_rename	\
-tst_rename2 tst_rename3 tst_h5_endians tst_atts_string_rewrite		\
-tst_hdf5_file_compat tst_fill_attr_vanish tst_rehash tst_filterparser	\
-tst_bug324 tst_types tst_atts3 tst_put_vars tst_elatefill tst_udf	\
-tst_put_vars_two_unlim_dim tst_bug1442
+tst_interops6 tst_interops_dims tst_enums tst_coords tst_coords2	\
+tst_coords3 tst_vars3 tst_vars4 tst_chunks tst_chunks2 tst_utf8		\
+tst_fills tst_fills2 tst_fillbug tst_xplatform tst_xplatform2		\
+tst_endian_fill tst_atts t_type cdm_sea_soundings tst_camrun tst_vl	\
+tst_atts1 tst_atts2 tst_vars2 tst_files5 tst_files6 tst_sync		\
+tst_h_scalar tst_rename tst_rename2 tst_rename3 tst_h5_endians		\
+tst_atts_string_rewrite tst_hdf5_file_compat tst_fill_attr_vanish	\
+tst_rehash tst_filterparser tst_bug324 tst_types tst_atts3		\
+tst_put_vars tst_elatefill tst_udf tst_put_vars_two_unlim_dim		\
+tst_bug1442
 
 # Temporary I hoped, but hoped in vain.
 if !ISCYGWIN
diff --git a/nc_test4/tst_interops_dims.c b/nc_test4/tst_interops_dims.c
new file mode 100644
index 000000000..d7f3c6c81
--- /dev/null
+++ b/nc_test4/tst_interops_dims.c
@@ -0,0 +1,132 @@
+/* This is part of the netCDF package.  Copyright 2019 University
+   Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
+   conditions of user Kai Mühlbauer.
+
+   Test handling of anonymous dimensions when netCDF reads a HDF5
+   file. This test partially contributed by user
+
+   Ed Hartnett, 11/13/2019
+*/
+#include <config.h>
+#include <nc_tests.h>
+#include "err_macros.h"
+#include <hdf5.h>
+#include <H5DSpublic.h>
+
+#define FILE_NAME "tst_interops_dims.h5"
+#define DIM_LEN 100
+
+int
+main(int argc, char **argv)
+{
+   printf("\n*** Testing HDF5/NetCDF-4 interoperability handling of HDF5 dimensions.\n");
+   printf("*** Checking handling of a HDF5 file with anon dims...");
+   {
+       hid_t       file_id, dataset_id, dataspace_id;  /* identifiers */
+       hsize_t     dims[2];
+
+       /* Create a new file using default properties. */
+       if ((file_id = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+           ERR;
+
+       /* Create the data space for the dataset. */
+       dims[0] = DIM_LEN;
+       dims[1] = DIM_LEN;
+       if ((dataspace_id = H5Screate_simple(2, dims, NULL)) < 0)
+           ERR;
+
+       /* Create the dataset. */
+       dataset_id = H5Dcreate2(file_id, "/dset", H5T_STD_I32BE, dataspace_id,
+                               H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+
+       /* End access to the dataset and release resources used by it. */
+       if (H5Dclose(dataset_id) < 0)
+           ERR;
+
+       /* Terminate access to the data space. */
+       if (H5Sclose(dataspace_id) < 0)
+           ERR;
+
+       /* Close the file. */
+       if (H5Fclose(file_id) < 0)
+           ERR;
+
+       /* Now open the file with netCDF. */
+       {
+           int ndims, nvars, ngatts, unlimdimid;
+           int ncid;
+           char dim_name[NC_MAX_NAME + 1];
+           size_t dim_len;
+
+           if (nc_open(FILE_NAME, NC_NOWRITE, &ncid))
+               ERR;
+           if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid))
+               ERR;
+           if (ndims != 2 || nvars != 1 || ngatts != 0 || unlimdimid != -1)
+               ERR;
+           if (nc_inq_dim(ncid, 0, dim_name, &dim_len))
+               ERR;
+           if (strcmp(dim_name, "phony_dim_0") || dim_len != DIM_LEN)
+               ERR;
+           if (nc_inq_dim(ncid, 1, dim_name, &dim_len))
+               ERR;
+           if (strcmp(dim_name, "phony_dim_1") || dim_len != DIM_LEN)
+               ERR;
+           if (nc_close(ncid))
+               ERR;
+       }
+   }
+   SUMMARIZE_ERR;
+   printf("*** Checking handling of a HDF5 file with anon dims and two datasets...");
+   {
+       hid_t       file_id, dataset_id, dataset_id_2, dataspace_id;  /* identifiers */
+       hsize_t     dims[2];
+
+       /* Create a new file using default properties. */
+       if ((file_id = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
+                                H5P_DEFAULT)) < 0) ERR;
+
+       /* Create the data space for the dataset. */
+       dims[0] = DIM_LEN;
+       dims[1] = DIM_LEN;
+       if ((dataspace_id = H5Screate_simple(2, dims, NULL)) < 0) ERR;
+
+       /* Create the datasets. */
+       if ((dataset_id = H5Dcreate2(file_id, "/dset", H5T_STD_I32BE, dataspace_id,
+                                    H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
+       if ((dataset_id_2 = H5Dcreate2(file_id, "/dset2", H5T_STD_I32BE, dataspace_id,
+                                    H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) ERR;
+
+       if (H5Dclose(dataset_id) < 0) ERR;
+       if (H5Dclose(dataset_id_2) < 0) ERR;
+       if (H5Sclose(dataspace_id) < 0) ERR;
+       if (H5Fclose(file_id) < 0) ERR;
+
+       /* Now open the file with netCDF. */
+       {
+           int ndims, nvars, ngatts, unlimdimid;
+           int ncid;
+           char dim_name[NC_MAX_NAME + 1];
+           size_t dim_len;
+
+           if (nc_open(FILE_NAME, NC_NOWRITE, &ncid))
+               ERR;
+           if (nc_inq(ncid, &ndims, &nvars, &ngatts, &unlimdimid))
+               ERR;
+           if (ndims != 2 || nvars != 2 || ngatts != 0 || unlimdimid != -1)
+               ERR;
+           if (nc_inq_dim(ncid, 0, dim_name, &dim_len))
+               ERR;
+           if (strcmp(dim_name, "phony_dim_0") || dim_len != DIM_LEN)
+               ERR;
+           if (nc_inq_dim(ncid, 1, dim_name, &dim_len))
+               ERR;
+           if (strcmp(dim_name, "phony_dim_1") || dim_len != DIM_LEN)
+               ERR;
+           if (nc_close(ncid))
+               ERR;
+       }
+   }
+   SUMMARIZE_ERR;
+   FINAL_RESULTS;
+}
diff --git a/nc_test4/tst_udf.c b/nc_test4/tst_udf.c
index 25f85f2d1..0d6413222 100644
--- a/nc_test4/tst_udf.c
+++ b/nc_test4/tst_udf.c
@@ -185,7 +185,7 @@ main(int argc, char **argv)
          if (nc_close(ncid)) ERR;
 
          /* Open file again and abort, which is the same as closing it. */
-         if (nc_open(FILE_NAME, mode[i], &ncid)) ERR;
+         if (nc_open(FILE_NAME, mode[i]|NC_NETCDF4, &ncid)) ERR;
          if (nc_inq_format(ncid, NULL) != TEST_VAL_42) ERR;
          if (nc_inq_format_extended(ncid, NULL, NULL) != TEST_VAL_42) ERR;
          if (nc_abort(ncid) != TEST_VAL_42) ERR;