@@ -63,9 +63,10 @@ Requires
63
63
If you want [OPeNDAP](http://opendap.org) support, add `--enable-dap`.
64
64
If you want HDF4 SD support, add `--enable-hdf4` and add
65
65
the location of the HDF4 headers and library to `$CPPFLAGS` and `$LDFLAGS`.
66
- - for MPI parallel IO support, MPI-enabled versions of the HDF5 and netcdf
67
- libraries are required, as is the [mpi4py](http://mpi4py.scipy.org) python
68
- module.
66
+ - for MPI parallel IO support, an MPI-enabled versions of the netcdf library
67
+ is required, as is the [mpi4py](http://mpi4py.scipy.org) python module.
68
+ Parallel IO further depends on the existence of MPI-enabled HDF5 or the
69
+ [PnetCDF](https://parallel-netcdf.github.io/) library.
69
70
70
71
71
72
Install
@@ -918,13 +919,14 @@ specified names.
918
919
919
920
## <div id='section13'>13) Parallel IO.
920
921
921
- If MPI parallel enabled versions of netcdf and hdf5 are detected, and
922
- [mpi4py](https://mpi4py.scipy.org) is installed, netcdf4-python will
923
- be built with parallel IO capabilities enabled. Since parallel IO
924
- uses features of HDF5, it can only be used with NETCDF4 or
925
- NETCDF4_CLASSIC formatted files. To use parallel IO,
926
- your program must be running in an MPI environment using
927
- [mpi4py](https://mpi4py.scipy.org).
922
+ If MPI parallel enabled versions of netcdf and hdf5 or pnetcdf are detected,
923
+ and [mpi4py](https://mpi4py.scipy.org) is installed, netcdf4-python will
924
+ be built with parallel IO capabilities enabled. Parallel IO of NETCDF4 or
925
+ NETCDF4_CLASSIC formatted files is only available if the MPI parallel HDF5
926
+ library is available. Parallel IO of classic netcdf-3 file formats is only
927
+ available if the [PnetCDF](https://parallel-netcdf.github.io/) library is
928
+ available. To use parallel IO, your program must be running in an MPI
929
+ environment using [mpi4py](https://mpi4py.scipy.org).
928
930
929
931
:::python
930
932
>>> from mpi4py import MPI
@@ -971,9 +973,12 @@ participate in doing IO. To toggle back and forth between
971
973
the two types of IO, use the `netCDF4.Variable.set_collective`
972
974
`netCDF4.Variable`method. All metadata
973
975
operations (such as creation of groups, types, variables, dimensions, or attributes)
974
- are collective. There are a couple of important limitatons of parallel IO:
976
+ are collective. There are a couple of important limitations of parallel IO:
975
977
976
- - only works with NETCDF4 or NETCDF4_CLASSIC formatted files.
978
+ - parallel IO for NETCDF4 or NETCDF4_CLASSIC formatted files is only available
979
+ if the netcdf library was compiled with MPI enabled HDF5.
980
+ - parallel IO for all classic netcdf-3 file formats is only available if the
981
+ netcdf library was compiled with PnetCDF.
977
982
- If a variable has an unlimited dimension, appending data must be done in collective mode.
978
983
If the write is done in independent mode, the operation will fail with a
979
984
a generic "HDF Error".
@@ -1202,7 +1207,7 @@ import_array()
1202
1207
include " constants.pyx"
1203
1208
include " membuf.pyx"
1204
1209
include " netCDF4.pxi"
1205
- IF HAS_NC_PAR :
1210
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
1206
1211
cimport mpi4py.MPI as MPI
1207
1212
from mpi4py.libmpi cimport MPI_Comm, MPI_Info, MPI_Comm_dup, MPI_Info_dup, \
1208
1213
MPI_Comm_free, MPI_Info_free, MPI_INFO_NULL,\
@@ -1240,7 +1245,8 @@ __has_nc_inq_format_extended__ = HAS_NC_INQ_FORMAT_EXTENDED
1240
1245
__has_cdf5_format__ = HAS_CDF5_FORMAT
1241
1246
__has_nc_open_mem__ = HAS_NC_OPEN_MEM
1242
1247
__has_nc_create_mem__ = HAS_NC_CREATE_MEM
1243
- __has_nc_par__ = HAS_NC_PAR
1248
+ __has_parallel4_support__ = HAS_PARALLEL4_SUPPORT
1249
+ __has_pnetcdf_support__ = HAS_PNETCDF_SUPPORT
1244
1250
_needsworkaround_issue485 = __netcdf4libversion__ < " 4.4.0" or \
1245
1251
(__netcdf4libversion__.startswith(" 4.4.0" ) and \
1246
1252
" -development" in __netcdf4libversion__)
@@ -1282,20 +1288,29 @@ _intnptonctype = {'i1' : NC_BYTE,
1282
1288
_format_dict = {' NETCDF3_CLASSIC' : NC_FORMAT_CLASSIC,
1283
1289
' NETCDF4_CLASSIC' : NC_FORMAT_NETCDF4_CLASSIC,
1284
1290
' NETCDF4' : NC_FORMAT_NETCDF4}
1291
+ # create dictionary mapping string identifiers to netcdf create format codes
1292
+ _cmode_dict = {' NETCDF3_CLASSIC' : NC_CLASSIC_MODEL,
1293
+ ' NETCDF4_CLASSIC' : NC_CLASSIC_MODEL | NC_NETCDF4,
1294
+ ' NETCDF4' : NC_NETCDF4}
1285
1295
IF HAS_CDF5_FORMAT:
1286
1296
# NETCDF3_64BIT deprecated, saved for compatibility.
1287
1297
# use NETCDF3_64BIT_OFFSET instead.
1288
1298
_format_dict[' NETCDF3_64BIT_OFFSET' ] = NC_FORMAT_64BIT_OFFSET
1289
1299
_format_dict[' NETCDF3_64BIT_DATA' ] = NC_FORMAT_64BIT_DATA
1300
+ _cmode_dict[' NETCDF3_64BIT_OFFSET' ] = NC_64BIT_OFFSET
1301
+ _cmode_dict[' NETCDF3_64BIT_DATA' ] = NC_64BIT_DATA
1290
1302
ELSE :
1291
1303
_format_dict[' NETCDF3_64BIT' ] = NC_FORMAT_64BIT
1304
+ _cmode_dict[' NETCDF3_64BIT' ] = NC_64BIT_OFFSET
1292
1305
# invert dictionary mapping
1293
1306
_reverse_format_dict = dict ((v, k) for k, v in _format_dict.iteritems())
1294
1307
# add duplicate entry (NETCDF3_64BIT == NETCDF3_64BIT_OFFSET)
1295
1308
IF HAS_CDF5_FORMAT:
1296
1309
_format_dict[' NETCDF3_64BIT' ] = NC_FORMAT_64BIT_OFFSET
1310
+ _cmode_dict[' NETCDF3_64BIT' ] = NC_64BIT_OFFSET
1297
1311
ELSE :
1298
1312
_format_dict[' NETCDF3_64BIT_OFFSET' ] = NC_FORMAT_64BIT
1313
+ _cmode_dict[' NETCDF3_64BIT_OFFSET' ] = NC_64BIT_OFFSET
1299
1314
1300
1315
# default fill_value to numpy datatype mapping.
1301
1316
default_fillvals = {# 'S1':NC_FILL_CHAR,
@@ -2084,7 +2099,7 @@ strings.
2084
2099
cdef char * path
2085
2100
cdef char namstring[NC_MAX_NAME+ 1 ]
2086
2101
cdef int cmode
2087
- IF HAS_NC_PAR :
2102
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2088
2103
cdef MPI_Comm mpicomm
2089
2104
cdef MPI_Info mpiinfo
2090
2105
@@ -2107,12 +2122,20 @@ strings.
2107
2122
raise ValueError (msg)
2108
2123
2109
2124
if parallel:
2110
- IF HAS_NC_PAR != 1 :
2125
+ IF HAS_PARALLEL4_SUPPORT ! = 1 and HAS_PNETCDF_SUPPORT != 1 :
2111
2126
msg= ' parallel mode requires MPI enabled netcdf-c'
2112
2127
raise ValueError (msg)
2113
2128
ELSE :
2114
- if format not in [' NETCDF4' ,' NETCDF4_CLASSIC' ]:
2115
- msg= ' parallel mode only works with format=NETCDF4 or NETCDF4_CLASSIC'
2129
+ parallel_formats = []
2130
+ IF HAS_PARALLEL4_SUPPORT:
2131
+ parallel_formats += [' NETCDF4' ,' NETCDF4_CLASSIC' ]
2132
+ IF HAS_PNETCDF_SUPPORT:
2133
+ parallel_formats += [' NETCDF3_CLASSIC' ,
2134
+ ' NETCDF3_64BIT_OFFSET' ,
2135
+ ' NETCDF3_64BIT_DATA' ,
2136
+ ' NETCDF3_64BIT' ]
2137
+ if format not in parallel_formats:
2138
+ msg= ' parallel mode only works with the following formats: ' + ' ' .join(parallel_formats)
2116
2139
raise ValueError (msg)
2117
2140
if comm is not None :
2118
2141
mpicomm = comm.ob_mpi
@@ -2122,9 +2145,7 @@ strings.
2122
2145
mpiinfo = info.ob_mpi
2123
2146
else :
2124
2147
mpiinfo = MPI_INFO_NULL
2125
- cmode = NC_MPIIO | NC_NETCDF4
2126
- if format == ' NETCDF4_CLASSIC' :
2127
- cmode = cmode | NC_CLASSIC_MODEL
2148
+ cmode = NC_MPIIO | _cmode_dict[format]
2128
2149
2129
2150
self ._inmemory = False
2130
2151
if mode == ' w' :
@@ -2144,7 +2165,7 @@ strings.
2144
2165
else :
2145
2166
if clobber:
2146
2167
if parallel:
2147
- IF HAS_NC_PAR :
2168
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2148
2169
ierr = nc_create_par(path, NC_CLOBBER | cmode, \
2149
2170
mpicomm, mpiinfo, & grpid)
2150
2171
ELSE :
@@ -2159,7 +2180,7 @@ strings.
2159
2180
ierr = nc_create(path, NC_CLOBBER, & grpid)
2160
2181
else :
2161
2182
if parallel:
2162
- IF HAS_NC_PAR :
2183
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2163
2184
ierr = nc_create_par(path, NC_NOCLOBBER | cmode, \
2164
2185
mpicomm, mpiinfo, & grpid)
2165
2186
ELSE :
@@ -2194,7 +2215,7 @@ strings.
2194
2215
version 4.4.1 or higher of the netcdf C lib, and rebuild netcdf4-python."""
2195
2216
raise ValueError (msg)
2196
2217
elif parallel:
2197
- IF HAS_NC_PAR :
2218
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2198
2219
ierr = nc_open_par(path, NC_NOWRITE | NC_MPIIO, \
2199
2220
mpicomm, mpiinfo, & grpid)
2200
2221
ELSE :
@@ -2205,7 +2226,7 @@ strings.
2205
2226
ierr = nc_open(path, NC_NOWRITE, & grpid)
2206
2227
elif mode == ' r+' or mode == ' a' :
2207
2228
if parallel:
2208
- IF HAS_NC_PAR :
2229
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2209
2230
ierr = nc_open_par(path, NC_WRITE | NC_MPIIO, \
2210
2231
mpicomm, mpiinfo, & grpid)
2211
2232
ELSE :
@@ -2217,7 +2238,7 @@ strings.
2217
2238
elif mode == ' as' or mode == ' r+s' :
2218
2239
if parallel:
2219
2240
# NC_SHARE ignored
2220
- IF HAS_NC_PAR :
2241
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2221
2242
ierr = nc_open_par(path, NC_WRITE | NC_MPIIO, \
2222
2243
mpicomm, mpiinfo, & grpid)
2223
2244
ELSE :
@@ -2231,7 +2252,7 @@ strings.
2231
2252
if clobber:
2232
2253
if parallel:
2233
2254
# NC_SHARE ignored
2234
- IF HAS_NC_PAR :
2255
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2235
2256
ierr = nc_create_par(path, NC_CLOBBER | cmode, \
2236
2257
mpicomm, mpiinfo, & grpid)
2237
2258
ELSE :
@@ -2246,7 +2267,7 @@ strings.
2246
2267
else :
2247
2268
if parallel:
2248
2269
# NC_SHARE ignored
2249
- IF HAS_NC_PAR :
2270
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
2250
2271
ierr = nc_create_par(path, NC_NOCLOBBER | cmode, \
2251
2272
mpicomm, mpiinfo, & grpid)
2252
2273
ELSE :
@@ -5345,7 +5366,7 @@ NC_CHAR).
5345
5366
turn on or off collective parallel IO access. Ignored if file is not
5346
5367
open for parallel access.
5347
5368
"""
5348
- IF HAS_NC_PAR :
5369
+ IF HAS_PARALLEL4_SUPPORT or HAS_PNETCDF_SUPPORT :
5349
5370
# set collective MPI IO mode on or off
5350
5371
if value:
5351
5372
ierr = nc_var_par_access(self ._grpid, self ._varid,
0 commit comments